Sortere en liste over dict av nøkkelen. Hvis det mangler nøkkelen, antar en fortløpende nummerering

stemmer
0

Jeg ønsker så sortere en liste av ordbøker av nøkkelen pos. Men hvis pos mangler i dict, jeg ønsker å holde orden på varen (e) og anta at pos er elementets en baserte indeksen i listen.

Dette fungerer fint, så lenge alle listeelementene er forskjellige:

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)

Produksjon:

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

Men det mislykkes hvis jeg har flere av de samme elementene, fordi da list.indexvil returnere den første forekomsten, snarere enn antatt posisjon.

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)

Faktiske produksjonen:

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

Forventet resultat:

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

Hvordan kan sorteringen endres for å returnere den forventede produksjonen?

Merk: elementet IDer er ikke garantert å være i hvilken som helst rekkefølge, det betyr 1,2,3,4,AAA,ABC,XYZhar blitt valgt tilfeldig.

Publisert på 09/10/2019 klokken 13:00
kilden bruker
På andre språk...                            


2 svar

stemmer
6

Bruk nummerere :

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)

Produksjon

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

For duplikater eksempel:

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)

Produksjon

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

En kanskje renere alternativ er å bruke itertools.count :

from itertools import count

counter = count(1)

result = sorted(L, key=lambda x: x.get("pos", next(counter)))
print(result)
Svarte 09/10/2019 kl. 13:08
kilden bruker

stemmer
0

Vi kan gjøre noe sånt som dette:

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

Svarte 09/10/2019 kl. 13:26
kilden bruker

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