web-dev-qa-db-fra.com

Forcer les éléments au début et à la fin de la liste

Comment puis-je modifier cette liste pour que tous les p's apparaît au début, le q's à la fin, et les valeurs intermédiaires sont triées par ordre alphabétique?

l = ['f','g','p','a','p','c','b','q','z','n','d','t','q']

J'aimerais donc avoir:

['p','p','a','b','c','d','f','g','n','t','z','q','q']
26
user10652346

Vous pouvez utiliser sorted avec le key suivant:

sorted(l, key = lambda s: (s!='p', s=='q', s))
['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']

Explication

Pour avoir une meilleure idée de la façon dont cela fonctionne, la compréhension de la liste suivante vise à répliquer ce qui est renvoyé par la fonction lambda définie dans l'argument key avant d'effectuer des comparaisons:

t = [(s!='p', s=='q', s) for s in pl]

print(t)
[(True, False, 'f'),
 (True, False, 'g'),
 (False, False, 'p'),
 (True, False, 'a'),
 (False, False, 'p'),
 (True, False, 'c'),
 (True, False, 'b'),
 (True, True, 'q'),
 (True, False, 'z'),
 (True, False, 'n'),
 (True, False, 'd'),
 (True, False, 't'),
 (True, True, 'q')]

Ce sera alors le key à utiliser pour trier les éléments de la liste, comme mentionné dans le documentation :

La valeur du paramètre clé doit être une fonction qui prend un seul argument et renvoie une clé à utiliser à des fins de tri.

Donc, en tenant compte du fait que False = 0 et True = 1, lorsque cette liste de tuples est triée, le résultat sera le suivant:

sorted(t)
[(False, False, 'p'),
 (False, False, 'p'),
 (True, False, 'a'),
 (True, False, 'b'),
 (True, False, 'c'),
 (True, False, 'd'),
 (True, False, 'f'),
 (True, False, 'g'),
 (True, False, 'n'),
 (True, False, 't'),
 (True, False, 'z'),
 (True, True, 'q'),
 (True, True, 'q')]
54
yatu

Une idée est d'utiliser un dictionnaire prioritaire avec une fonction personnalisée. Ceci est naturellement extensible si vous souhaitez inclure des critères supplémentaires.

L = ['f','g','p','a','p','c','b','q','z','n','d','t','q']

def sort_func(x):
    priority = {'p': 0, 'q': 2}
    return priority.get(x, 1), x

res = sorted(L, key=sort_func)

print(res)

['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']
19
jpp

Utilisez le paramètre key dans trié :

l = ['f','g','p','a','p','c','b','q','z','n','d','t','q']

def key(c):
    if c == 'q':
        return (2, c)
    Elif c == 'p':
        return (0, c)
    return (1, c)


result = sorted(l, key=key)
print(result)

Sortie

['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']
14
Daniel Mesejo

Définissez simplement une fonction clé appropriée:

>>> def _key(x):
...     if x == 'p':
...         return -1
...     Elif x == 'q':
...         return float('inf')
...     else:
...         return ord(x)
...
>>> l = ['f','g','p','a','p','c','b','q','z','n','d','t','q']
>>> sorted(l, key=_key)
['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']

Notez que chaque caractère est mappé sur un entier> = 0, nous pouvons donc simplement compter sur ord, et puisque -1 sera toujours inférieur à tout ce qui est retourné par ord, nous pouvons l'utiliser pour p, et pour q, nous pouvons utiliser l'infini, il sera donc toujours supérieur à quelque chose retourné par ord.

7
juanpa.arrivillaga

Vous pouvez trouver tous les éléments p et q, filtrer la liste d'origine, puis trier:

l = ['f','g','p','a','p','c','b','q','z','n','d','t','q']
_ps, _qs = [i for i in l if i == 'p'], [i for i in l if i == 'q']
new_l = _ps+sorted(filter(lambda x:x not in {'q', 'p'}, l))+_qs

Sortie:

['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']
4
Ajax1234

Vous pouvez également vous stocker avant, milieu et se termine dans un collections.defaultdict() , puis ajoutez simplement les trois listes à la fin:

from collections import defaultdict

l = ["f", "g", "p", "a", "p", "c", "b", "q", "z", "n", "d", "t", "q"]

keys = {"p": "front", "q": "end"}

d = defaultdict(list)
for item in l:
    d[keys.get(item, "middle")].append(item)

print(d["front"] + sorted(d["middle"]) + d["end"])
# ['p', 'p', 'a', 'b', 'c', 'd', 'f', 'g', 'n', 't', 'z', 'q', 'q']
2
RoadRunner

La solution à cette question est:

  1. Trouvez d'abord tous les éléments p et q dans la liste.
  2. Filtrez la liste d'origine.
  3. Ensuite, triez enfin la liste.

list = ['f','g','p','a','p','c','b','q','z','n','d','t','q'];
noOfPs = [i for i in l if i == 'p']; 
noOfQs = [i for i in l if i == 'q'];
resultList= noOfPs + sorted(filter(lambda x:x not in {'q', 'p'}, l))+ noOfQs 
1
Sagar P. Ghagare