Hoe herhaal ik in Python een woordenboek in gesorteerde sleutelvolgorde?

Er is een bestaande functie die eindigt op het volgende, waarbij deen woordenboek is:

return d.iteritems()

die een ongesorteerde iterator voor een bepaald woordenboek retourneert. Ik wil graag een iterator retourneren die de items doorloopt die op sleutelzijn gesorteerd. Hoe doe ik dat?


Antwoord 1, autoriteit 100%

Heb dit niet erg uitgebreid getest, maar werkt in Python 2.5.2.

>>> d = {"x":2, "h":15, "a":2222}
>>> it = iter(sorted(d.iteritems()))
>>> it.next()
('a', 2222)
>>> it.next()
('h', 15)
>>> it.next()
('x', 2)
>>>

Als je gewend bent om for key, value in d.iteritems(): ...te doen in plaats van iterators, zal dit nog steeds werken met de bovenstaande oplossing

>>> d = {"x":2, "h":15, "a":2222}
>>> for key, value in sorted(d.iteritems()):
>>>     print(key, value)
('a', 2222)
('h', 15)
('x', 2)
>>>

Gebruik bij Python 3.x d.items()in plaats van d.iteritems()om een ​​iterator te retourneren.


Antwoord 2, autoriteit 46%

Gebruik de functie sorted():

return sorted(dict.iteritems())

Als je een echte iterator wilt over de gesorteerde resultaten, aangezien sorted()een lijst retourneert, gebruik dan:

return iter(sorted(dict.iteritems()))

Antwoord 3, autoriteit 23%

De sleutels van een dictaat worden opgeslagen in een hashtabel, dus dat is hun ‘natuurlijke volgorde’, d.w.z. psuedo-willekeurig. Elke andere bestelling is een concept van de consument van het dictaat.

sorted() retourneert altijd een lijst, geen dictaat. Als je het een dict.items() doorgeeft (die een lijst met tuples produceert), zal het een lijst met tupels retourneren [(k1,v1), (k2,v2), …] die in een lus kan worden gebruikt op een manier die erg lijkt op een dictaat, maar het is hoe dan ook geen dictaat!

foo = {
    'a':    1,
    'b':    2,
    'c':    3,
    }
print foo
>>> {'a': 1, 'c': 3, 'b': 2}
print foo.items()
>>> [('a', 1), ('c', 3), ('b', 2)]
print sorted(foo.items())
>>> [('a', 1), ('b', 2), ('c', 3)]

Het volgende voelt als een dictaat in een lus, maar dat is het niet, het is een lijst met tuples die worden uitgepakt in k,v:

for k,v in sorted(foo.items()):
    print k, v

Ruwweg gelijk aan:

for k in sorted(foo.keys()):
    print k, foo[k]

Antwoord 4, autoriteit 18%

Gregs antwoord is juist. Merk op dat je in Python 3.0 moet doen

sorted(dict.items())

aangezien iteritemsverdwenen zullen zijn.


Antwoord 5, autoriteit 4%

Je kunt nu ook OrderedDictgebruiken in Python 2.7:

>>> from collections import OrderedDict
>>> d = OrderedDict([('first', 1),
...                  ('second', 2),
...                  ('third', 3)])
>>> d.items()
[('first', 1), ('second', 2), ('third', 3)]

Hier heb je de wat is er nieuwpagina voor versie 2.7 en de OrderedDict-API.


Antwoord 6, autoriteit 3%

Over het algemeen kun je een dictaat als volgt sorteren:

for k in sorted(d):
    print k, d[k]

Voor het specifieke geval in de vraag, met een “drop in vervanging” voor d.iteritems(), voeg een functie toe zoals:

def sortdict(d, **opts):
    # **opts so any currently supported sorted() options can be passed
    for k in sorted(d, **opts):
        yield k, d[k]

en dus verandert de eindregel van

return dict.iteritems()

naar

return sortdict(dict)

of

return sortdict(dict, reverse = True)

Antwoord 7, autoriteit 3%

>>> import heapq
>>> d = {"c": 2, "b": 9, "a": 4, "d": 8}
>>> def iter_sorted(d):
        keys = list(d)
        heapq.heapify(keys) # Transforms to heap in O(N) time
        while keys:
            k = heapq.heappop(keys) # takes O(log n) time
            yield (k, d[k])
>>> i = iter_sorted(d)
>>> for x in i:
        print x
('a', 4)
('b', 9)
('c', 2)
('d', 8)

Deze methode heeft nog steeds een O(N log N) sortering, maar na een korte lineaire heapify levert het de items in gesorteerde volgorde op, waardoor het theoretisch efficiënter is als je niet altijd de hele lijst nodig hebt.


Antwoord 8, autoriteit 2%

Als je wilt sorteren op de volgorde waarin items zijn ingevoegd in plaats van op de volgorde van de toetsen, moet je eens kijken in Python’s collections.OrderedDict. (alleen Python 3)


Antwoord 9, autoriteit 2%

gesorteerd retourneert een lijst, vandaar uw fout wanneer u erover probeert te herhalen,
maar omdat je geen dictaat kunt bestellen, krijg je te maken met een lijst.

Ik heb geen idee wat de grotere context van je code is, maar je zou kunnen proberen een . toe te voegen
iterator naar de resulterende lijst.
zoals dit misschien?:

return iter(sorted(dict.iteritems()))

Natuurlijk krijg je nu tuples terug, want Sort heeft je dictaat veranderd in een lijst met tuples

ex:
zeg dat je dictaat was:
{'a':1,'c':3,'b':2}
gesorteerd verandert het in een lijst:

[('a',1),('b',2),('c',3)]

dus als je de lijst daadwerkelijk herhaalt, krijg je (in dit voorbeeld) een tuple terug
samengesteld uit een string en een geheel getal, maar je kunt er tenminste overheen herhalen.


Antwoord 10

Ervan uitgaande dat u CPython 2.x gebruikt en een groot woordenboek mydict hebt, zal het gebruik van gesorteerd(mydict) langzaam gaan omdat gesorteerd een gesorteerde lijst van de sleutels van mydict opbouwt.

In dat geval wil je misschien mijn besteldedict-pakket bekijken dat een C-implementatie van sorteddictin C bevat. Vooral als je de gesorteerde lijst met sleutels meerdere keren in verschillende stadia moet doorlopen ( dwz aantal elementen) van de levensduur van de woordenboeken.

http://anthon.home.xs4all.nl/Python/ordereddict/

Other episodes