Rozważmy następujący słownik, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Chcę zwrócić pierwszy N par klucz: wartość z d (w tym przypadku N <= 4). Jaka jest najskuteczniejsza metoda zrobienia tego?
Rozważmy następujący słownik, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Chcę zwrócić pierwszy N par klucz: wartość z d (w tym przypadku N <= 4). Jaka jest najskuteczniejsza metoda zrobienia tego?
Odpowiedzi:
Nie ma czegoś takiego jak „pierwsze n” kluczy, ponieważ a dict
nie pamięta, które klucze zostały wstawione jako pierwsze.
Możesz jednak uzyskać dowolne n par klucz-wartość:
n_items = take(n, d.iteritems())
Wykorzystuje to wykonanie take
z itertools
receptur :
from itertools import islice
def take(n, iterable):
"Return first n items of the iterable as a list"
return list(islice(iterable, n))
Zobacz, jak działa online: ideone
Aktualizacja dla Pythona 3.6
n_items = take(n, d.items())
iteritems
powinien zostać zastąpiony przez items
dla ludzi w Pythonie 3
take()
gdzieś częścią kodu Pythona? A może jest to wyłącznie funkcja, którą zdefiniowałeś w swojej odpowiedzi? Pytając, jakby to była część bazy kodu, nie mogę go znaleźć / zaimportować. :)
Bardzo skutecznym sposobem na pobranie czegokolwiek jest połączenie wyrażeń listowych lub słownikowych z wycinaniem. Jeśli nie musisz zamawiać elementów (potrzebujesz tylko n losowych par), możesz użyć wyrażenia słownikowego w następujący sposób:
# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}
Ogólnie rzecz biorąc, takie rozumienie jest zawsze szybsze do wykonania niż jego odpowiednik w pętli „for x in y”. Ponadto, używając .keys () do tworzenia listy kluczy słownika i dzielenia tej listy, unikasz „dotykania” niepotrzebnych klawiszy podczas tworzenia nowego słownika.
Jeśli nie potrzebujesz kluczy (tylko wartości), możesz użyć rozumienia listowego:
first2vals = [v for v in mydict.values()[:2]]
Jeśli potrzebujesz wartości posortowanych na podstawie ich kluczy, nie stanowi to większego problemu:
first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]
lub jeśli potrzebujesz również kluczy:
first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}
Pythona dict
nie są uporządkowane, więc nie ma sensu prosić o „pierwsze N” kluczy.
collections.OrderedDict
Klasa jest dostępna, jeśli to jest to, czego potrzebujesz. Możesz skutecznie uzyskać jego pierwsze cztery elementy jako
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.islice
pozwala leniwie pobrać wycinek elementów z dowolnego iteratora. Jeśli chcesz, aby wynik był wielokrotnego użytku, musisz przekonwertować go na listę lub coś podobnego, na przykład:
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))
Zasadniczo zamień widok (dict_items) na iterator, a następnie wykonaj iterację za pomocą next ().
Nie widziałem tego tutaj. Nie będzie uporządkowana, ale najprostsza składniowo, jeśli potrzebujesz po prostu pobrać niektóre elementy ze słownika.
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]}
pojawia się ten błąd: (akcje to nazwa mojego słownika)
Aby pobrać N pierwszych elementów ze słownika Pythona, można użyć następującego wiersza kodu:
list(dictionaryName.items())[:N]
W Twoim przypadku możesz to zmienić na:
list(d.items())[:4]
Zobacz PEP 0265 na temat sortowania słowników. Następnie użyj wyżej wymienionego kodu iterowalnego.
Jeśli potrzebujesz większej wydajności w posortowanych parach klucz-wartość. Użyj innej struktury danych. To znaczy taki, który utrzymuje posortowany porządek i skojarzenia klucz-wartość.
Na przykład
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)]
w py3, to załatwi sprawę
{A:N for (A,N) in [x for x in d.items()][:4]}
{'a': 3, 'b': 2, 'c': 3, 'd': 4}
Zależy to od tego, co jest „najbardziej wydajne” w Twoim przypadku.
Jeśli potrzebujesz tylko pół-losowej próbki dużego słownika foo
, użyj foo.iteritems()
i pobierz z niego tyle wartości, ile potrzebujesz, jest to leniwa operacja, która pozwala uniknąć tworzenia jawnej listy kluczy lub elementów.
Jeśli musisz najpierw posortować klucze, nie ma sposobu, aby użyć czegoś takiego jak keys = foo.keys(); keys.sort()
lub sorted(foo.iterkeys())
, będziesz musiał utworzyć jawną listę kluczy. Następnie kawałek lub iteracji pierwszego N keys
.
A tak przy okazji, dlaczego zależy ci na „efektywnym” sposobie? Czy profilowałeś swój program? Jeśli tego nie zrobiłeś, najpierw skorzystaj z oczywistego i łatwego do zrozumienia sposobu. Są szanse, że poradzi sobie całkiem nieźle, nie stając się wąskim gardłem.
Możesz podejść do tego na wiele sposobów. Jeśli zamówienie jest ważne, możesz to zrobić:
for key in sorted(d.keys()):
item = d.pop(key)
Jeśli zamówienie nie jest problemem, możesz to zrobić:
for i in range(4):
item = d.popitem()
value
raczej nazwać niż item
dla jasności.
Słownik nie zachowuje porządku, więc przed wybraniem pierwszych N par klucz-wartość posortujmy je.
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
Teraz możemy pobrać górne „N” elementów:, używając struktury metody takiej jak:
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
aby uzyskać 2 górne elementy, po prostu użyj tej struktury:
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)
rozważ dyktando
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
from itertools import islice
n = 3
list(islice(d.items(),n))
islice załatwi sprawę :) mam nadzieję, że to pomoże!
To może nie być zbyt eleganckie, ale działa dla mnie:
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
Wypróbowałem kilka powyższych odpowiedzi i zauważyłem, że niektóre z nich są zależne od wersji i nie działają w wersji 3.7.
Zwracam również uwagę, że od 3.6 wszystkie słowniki są uporządkowane według kolejności wstawiania pozycji.
Mimo że słowniki są zamawiane od 3.6, niektóre stwierdzenia, których oczekujesz od pracy z uporządkowanymi strukturami, wydają się nie działać.
Odpowiedź na pytanie OP, która była dla mnie najlepsza.
itr = iter(dic.items())
lst = [next(itr) for i in range(3)]
lst = list(d.items())[:N]
def GetNFirstItems(self):
self.dict = {f'Item{i + 1}': round(uniform(20.40, 50.50), 2) for i in range(10)}#Example Dict
self.get_items = int(input())
for self.index,self.item in zip(range(len(self.dict)),self.dict.items()):
if self.index==self.get_items:
break
else:
print(self.item,",",end="")
Niezwykłe podejście, ponieważ zapewnia intensywną złożoność czasu O (N).
list(d.items())[:4]
. list () jest podstawową implementacją wielu odpowiedzi.