Trier une liste de dict par clé. Si la clé est manquante, on suppose une numérotation consécutive

voix
0

Je veux donc trier une liste de dictionnaires par la clé « pos ». Toutefois, si « pos » manque dans le dict, je veux garder l'ordre de l'élément (s) et supposons que « pos » est l'indice de base 1 de l'article dans la liste.

Cela fonctionne très bien, aussi longtemps que tous les éléments de la liste sont différents:

L = [
    {   id: 1 }, # assume pos: 1
    {   id: 2 }, # assume pos: 2
    {   id: 3 }, # assume pos: 3
    {   id: 4 }, # assume pos: 4
    {   id: ZZZ }, # assume pos: 5
    {   id: AAA }, # assume pos: 6
    {   id: ABC, pos: 3.2 },
    {   id: XYZ, pos: 3.1 },
]

s = sorted(L,key=lambda i:i.get(pos,L.index(i)+1))
print(s)

Sortie:

[{'id': '1'}, {'id': '2'}, {'id': '3'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': '4'}, {'id': 'ZZZ'}, {'id': 'AAA'}]

Mais il échoue si j'ai plusieurs des mêmes éléments, car alors list.indexretournera la première occurence, plutôt que la « position supposée ».

L = [
    {   id: 1 }, # assume pos: 1
    {   id: 1 }, # assume pos: 2
    {   id: 1 }, # assume pos: 3
    {   id: 1 }, # assume pos: 4
    {   id: 1 }, # assume pos: 5
    {   id: AAA }, # assume pos: 6
    {   id: ABC, pos: 3.2 },
    {   id: XYZ, pos: 3.1 },
]

s = sorted(L,key=lambda i:i.get(pos,L.index(i)+1))
print(s)

La production réelle:

[{'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': 'AAA'}]

Production attendue:

[{'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': '1'}, {'id': '1'}, {'id': 'AAA'}]

Comment le tri peut être modifié pour retourner le résultat attendu?

Remarque: les ID de poste ne sont pas garantis dans l'ordre, que des moyens 1,2,3,4,AAA,ABC,XYZont été choisis de façon arbitraire.

Créé 09/10/2019 à 13:00
source utilisateur
Dans d'autres langues...                            


2 réponses

voix
6

Utilisez enumerate :

L = [
    {"id": "1"},  # assume pos: 1
    {"id": "2"},  # assume pos: 2
    {"id": "3"},  # assume pos: 3
    {"id": "4"},  # assume pos: 4
    {"id": "ZZZ"},  # assume pos: 5
    {"id": "AAA"},  # assume pos: 6
    {"id": "ABC", "pos": 3.2},
    {"id": "XYZ", "pos": 3.1},
]

result = [e for _, e in sorted(enumerate(L, 1), key=lambda x: x[1].get("pos", x[0]))]

print(result)

Sortie

[{'id': '1'}, {'id': '2'}, {'id': '3'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': '4'}, {'id': 'ZZZ'}, {'id': 'AAA'}]

Pour l'exemple des doublons:

L = [
    {"id": "1"},  # assume pos: 1
    {"id": "1"},  # assume pos: 2
    {"id": "1"},  # assume pos: 3
    {"id": "1"},  # assume pos: 4
    {"id": "1"},  # assume pos: 5
    {"id": "AAA"},  # assume pos: 6
    {"id": "ABC", "pos": 3.2},
    {"id": "XYZ", "pos": 3.1},
]

result = [e for _, e in sorted(enumerate(L, 1), key=lambda x: x[1].get("pos", x[0]))]

print(result)

Sortie

[{'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': '1'}, {'id': '1'}, {'id': 'AAA'}]

Une alternative peut - être plus propre est d'utiliser itertools.count :

from itertools import count

counter = count(1)

result = sorted(L, key=lambda x: x.get("pos", next(counter)))
print(result)
Créé 09/10/2019 à 13:08
source utilisateur

voix
0

Nous pouvons faire quelque chose comme ceci:

d = [
    {"id": "1"}, # assume pos: 1
    {"id": "1"}, # assume pos: 2
    {"id": "1"}, # assume pos: 3
    {"id": "1"}, # assume pos: 4
    {"id": "1"}, # assume pos: 5
    {"id": "AAA"}, # assume pos: 6
    {"id": "ABC", "pos": 3.2},
    {"id": "XYZ", "pos": 3.1},
]


def my_compare(x):
    if 'pos' in x[1]:
        return x[1]['pos']
    return x[0] + 1

sorted_d = [x[1] for x in sorted(enumerate(d), key=my_compare)]

expected_output = [
    {'id': '1'}, 
    {'id': '1'}, 
    {'id': '1'}, 
    {'id': 'XYZ','pos': 3.1}, 
    {'id': 'ABC','pos': 3.2}, 
    {'id': '1'}, 
    {'id': '1'}, 
    {'id': 'AAA'},
]
assert sorted_d == expected_output

Créé 09/10/2019 à 13:26
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more