Sortarea unei liste de dict de chei. În cazul în care cheia lipsește, să își asume o numerotare consecutivă

voturi
0

Vreau atât sorta o listă de dicționare de tasta „pos“. Cu toate acestea, în cazul în care „POS“ lipsește în dict, vreau să păstreze ordinea elementului (e) și să presupunem că „POS“ este indicele 1 bazat pe element din listă.

Acest lucru este bine, atâta timp cât toate elementele de listă sunt diferite:

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)

ieşire:

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

Dar nu , dacă am mai multe din aceleași elemente, pentru că atunci se list.indexva întoarce prima apariție, mai degrabă decât „poziția asumată“.

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)

ieșire real:

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

ieșire de așteptat:

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

Cum poate fi modificat sortarea pentru a reveni ieșire de așteptat?

Notă: ID - urile de elemente care nu sunt garantate de a fi , în orice ordine, înseamnă că 1,2,3,4,AAA,ABC,XYZau fost alese în mod arbitrar.

Întrebat 09/10/2019 la 13:00
sursa de către utilizator
În alte limbi...                            


2 răspunsuri

voturi
6

Utilizare 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)

producție

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

Pentru exemplul duplicate:

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)

producție

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

O alternativă , poate , mai curat este de a utiliza itertools.count :

from itertools import count

counter = count(1)

result = sorted(L, key=lambda x: x.get("pos", next(counter)))
print(result)
Publicat 09/10/2019 la 13:08
sursa de către utilizator

voturi
0

Putem face ceva de genul:

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

Publicat 09/10/2019 la 13:26
sursa de către utilizator

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