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']
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')]
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']
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']
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
.
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']
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']
La solution à cette question est:
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