Betrachten Sie das folgende Wörterbuch, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Ich möchte die ersten N Schlüssel: Wert-Paare von d zurückgeben (in diesem Fall N <= 4). Was ist die effizienteste Methode dafür?
Betrachten Sie das folgende Wörterbuch, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Ich möchte die ersten N Schlüssel: Wert-Paare von d zurückgeben (in diesem Fall N <= 4). Was ist die effizienteste Methode dafür?
Antworten:
Es gibt keine "ersten n" Tasten, da a dictsich nicht daran erinnert, welche Tasten zuerst eingefügt wurden.
Sie können jedoch n beliebige Schlüssel-Wert-Paare erhalten:
n_items = take(n, d.iteritems())
Dies nutzt die Implementierung von takeaus den itertoolsRezepten :
from itertools import islice
def take(n, iterable):
"Return first n items of the iterable as a list"
return list(islice(iterable, n))
Sehen Sie, wie es online funktioniert: ideone
Update für Python 3.6
n_items = take(n, d.items())
iteritemssollte durch itemsfür Leute auf Python 3 ersetzt werden
take()irgendwo ein Teil der Python-Codebasis? Oder ist es nur die Funktion, die Sie in Ihrer Antwort hier definiert haben? Wenn ich frage, ob es Teil der Codebasis ist, kann ich es nicht finden / importieren. :)
Eine sehr effiziente Möglichkeit, etwas abzurufen, besteht darin, das Verständnis von Listen oder Wörterbüchern mit dem Schneiden zu kombinieren. Wenn Sie die Artikel nicht bestellen müssen (Sie möchten nur n zufällige Paare), können Sie ein Wörterbuchverständnis wie das folgende verwenden:
# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}
Im Allgemeinen ist ein solches Verständnis immer schneller auszuführen als die entsprechende Schleife "für x in y". Wenn Sie mit .keys () eine Liste der Wörterbuchschlüssel erstellen und diese Liste aufteilen, vermeiden Sie außerdem, dass Sie beim Erstellen des neuen Wörterbuchs unnötige Schlüssel berühren.
Wenn Sie die Schlüssel (nur die Werte) nicht benötigen, können Sie ein Listenverständnis verwenden:
first2vals = [v for v in mydict.values()[:2]]
Wenn Sie die Werte nach ihren Schlüsseln sortieren müssen, ist das kein Problem mehr:
first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]
oder wenn Sie auch die Schlüssel benötigen:
first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}
Pythons dictsind nicht bestellt, daher ist es sinnlos, nach den "ersten N" -Tasten zu fragen.
Die collections.OrderedDictKlasse ist verfügbar, wenn Sie dies benötigen. Sie könnten die ersten vier Elemente effizient als erhalten
import itertools
import collections
d = collections.OrderedDict((('foo', 'bar'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')))
x = itertools.islice(d.items(), 0, 4)
for key, value in x:
print key, value
itertools.isliceMit dieser Option können Sie träge Elemente aus jedem Iterator entfernen. Wenn Sie möchten, dass das Ergebnis wiederverwendbar ist, müssen Sie es in eine Liste oder ähnliches konvertieren:
x = list(itertools.islice(d.items(), 0, 4))
foo = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6}
iterator = iter(foo.items())
for i in range(3):
print(next(iterator))
Verwandeln Sie die Ansicht (dict_items) in einen Iterator und iterieren Sie sie dann mit next ().
Habe es hier nicht gesehen. Wird nicht bestellt, sondern syntaktisch am einfachsten, wenn Sie nur einige Elemente aus einem Wörterbuch entnehmen müssen.
n = 2
{key:value for key,value in d.items()[0:n]}
TypeError: 'dict_items' object is not subscriptable {key:value for key,value in stocks.items()[0:n]} (Aktien ist der Name meines Wörterbuchs)
Um die Top-N-Elemente aus Ihrem Python-Wörterbuch zu erhalten, können Sie die folgende Codezeile verwenden:
list(dictionaryName.items())[:N]
In Ihrem Fall können Sie Folgendes ändern:
list(d.items())[:4]
Siehe PEP 0265 zum Sortieren von Wörterbüchern. Verwenden Sie dann den oben genannten iterierbaren Code.
Wenn Sie mehr Effizienz bei den sortierten Schlüssel-Wert-Paaren benötigen. Verwenden Sie eine andere Datenstruktur. Das heißt, eine, die die sortierte Reihenfolge und die Schlüsselwertzuordnungen beibehält.
Z.B
import bisect
kvlist = [('a', 1), ('b', 2), ('c', 3), ('e', 5)]
bisect.insort_left(kvlist, ('d', 4))
print kvlist # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
In py3 reicht dies aus
{A:N for (A,N) in [x for x in d.items()][:4]}
{'a': 3, 'b': 2, 'c': 3, 'd': 4}
Dies hängt davon ab, was in Ihrem Fall am effizientesten ist.
Wenn Sie nur eine halbzufällige Stichprobe eines riesigen Wörterbuchs fooverwenden möchten , verwenden foo.iteritems()und verwenden Sie so viele Werte, wie Sie benötigen. Dies ist eine verzögerte Operation, bei der die Erstellung einer expliziten Liste von Schlüsseln oder Elementen vermieden wird.
Wenn Sie zuerst Schlüssel sortieren müssen, führt kein Weg daran vorbei, keys = foo.keys(); keys.sort()oder sorted(foo.iterkeys())Sie müssen eine explizite Liste von Schlüsseln erstellen. Dann schneiden oder durchlaufen ersten N keys.
Übrigens, warum interessiert Sie der "effiziente" Weg? Haben Sie Ihr Programm profiliert? Wenn Sie dies nicht getan haben, verwenden Sie zuerst den offensichtlichen und leicht verständlichen Weg. Die Chancen stehen gut, dass es ziemlich gut läuft, ohne zu einem Engpass zu werden.
Sie können dies auf verschiedene Arten angehen. Wenn die Reihenfolge wichtig ist, können Sie dies tun:
for key in sorted(d.keys()):
item = d.pop(key)
Wenn die Bestellung kein Problem darstellt, können Sie dies tun:
for i in range(4):
item = d.popitem()
valueeher nennen als itemaus Gründen der Klarheit.
Das Wörterbuch behält keine Reihenfolge bei. Bevor Sie also die ersten N Schlüsselwertpaare auswählen, können Sie es sortieren.
import operator
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
#itemgetter(0)=sort by keys, itemgetter(1)=sort by values
Jetzt können wir die obersten 'N'-Elemente abrufen: Mit der folgenden Methodenstruktur:
def return_top(elements,dictionary_element):
'''Takes the dictionary and the 'N' elements needed in return
'''
topers={}
for h,i in enumerate(dictionary_element):
if h<elements:
topers.update({i:dictionary_element[i]})
return topers
Um die Top 2 Elemente zu erhalten, verwenden Sie einfach diese Struktur:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
d=return_top(2,d)
print(d)
Betrachten Sie ein Diktat
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
from itertools import islice
n = 3
list(islice(d.items(),n))
islice wird den Trick machen :) hoffe es hilft!
Das mag nicht sehr elegant sein, funktioniert aber für mich:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
x= 0
for key, val in d.items():
if x == 2:
break
else:
x += 1
# Do something with the first two key-value pairs
Ich habe einige der obigen Antworten ausprobiert und festgestellt, dass einige davon versionabhängig sind und in Version 3.7 nicht funktionieren.
Ich stelle auch fest, dass seit 3.6 alle Wörterbücher nach der Reihenfolge geordnet sind, in der Elemente eingefügt werden.
Obwohl Wörterbücher seit 3.6 bestellt wurden, scheinen einige der Anweisungen, die Sie für geordnete Strukturen erwarten, nicht zu funktionieren.
Die Antwort auf die OP-Frage, die für mich am besten funktioniert hat.
itr = iter(dic.items())
lst = [next(itr) for i in range(3)]
lst = list(d.items())[:N]
list(d.items())[:4]. list () ist die zugrunde liegende Implementierung für viele der Antworten.