Sorteer een lijst van dict met een sleutel. Als sleutel ontbreekt, wordt uitgegaan van een doorlopende nummering

stemmen
0

Ik wil zo gekozen een lijst van woordenboeken door de toets pos. Echter, als pos ontbreekt in het dict, ik wil de volgorde van het item (s) te houden en gaan ervan uit dat pos is 1 gebaseerde index van het item in de lijst.

Dit werkt prima, zolang alle lijst items zijn verschillend:

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)

Output:

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

Maar het mislukt als ik meerdere van dezelfde items, want dan list.indexzal het eerste optreden terug te keren, in plaats van de veronderstelde positie.

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)

Werkelijke output:

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

Verwachte resultaten:

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

Hoe kan de sortering worden aangepast aan de verwachte output terug te keren?

Let op: het item-ID's zijn niet gegarandeerd te zijn in willekeurige volgorde, dat betekent 1,2,3,4,AAA,ABC,XYZzijn willekeurig gekozen.

De vraag is gesteld op 09/10/2019 om 13:00
bron van user
In andere talen...                            


2 antwoorden

stemmen
6

Gebruik opsommen :

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)

uitgang

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

Voor de duplicaten Bijvoorbeeld:

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)

uitgang

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

Een misschien schoner alternatief is om te gebruiken itertools.count :

from itertools import count

counter = count(1)

result = sorted(L, key=lambda x: x.get("pos", next(counter)))
print(result)
antwoordde op 09/10/2019 om 13:08
bron van user

stemmen
0

We kunnen zoiets als dit te doen:

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

antwoordde op 09/10/2019 om 13:26
bron van user

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