Wyobraź sobie, że masz:
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
Jaki jest najprostszy sposób na utworzenie następującego słownika?
a_dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
python
list
dictionary
Guido
źródło
źródło
dictionary = {zip(keys, values)}
to nie zadziała. Musisz jawnie zadeklarować jakodict(...)
{thing}
jest cukrem syntaktycznym do skonstruowaniaset()
zawierającego jeden element.{*iterable}
jest cukrem syntaktycznym do skonstruowaniaset
zawierającego kilka elementów.{k:v}
lub{**mapping}
będzie skonstruowaćdict
, ale to składniowo zupełnie odrębne.{}
do słowników. W rzeczywistości, jeśli spróbujemy,type({})
wynik będziedict
. Ale rzeczywiście, jeśli spróbujemy,type({thing})
wynik będzieset
.{k:v for k, v in zip(keys, values)}
. Okazuje się, że możemy. +1.Najbardziej wydajny
dict
konstruktorzip
W Pythonie 3 zip zwraca teraz leniwy iterator i jest to obecnie najbardziej wydajne podejście.
dict(zip(keys, values))
wymaga każdorazowego jednorazowego globalnego wyszukiwaniadict
izip
, ale nie tworzy niepotrzebnych pośrednich struktur danych ani nie musi zajmować się lokalnymi przeglądami w aplikacji funkcji.Drugie miejsce, zrozumienie dykta:
Drugim miejscem do korzystania z konstruktora dict jest użycie natywnej składni rozumienia dict (nie rozumienia listy , jak inni błędnie to powiedzieli):
Wybierz tę opcję, gdy chcesz mapować lub filtrować na podstawie kluczy lub wartości.
W Pythonie 2
zip
zwraca listę, aby uniknąć tworzenia niepotrzebnej listy, użyjizip
zamiast tego (aliasy do zip mogą zmniejszyć zmiany kodu po przejściu do Pythona 3).Tak więc nadal (2.7):
Python 2, idealny dla <= 2.6
izip
fromitertools
staje sięzip
w Pythonie 3.izip
jest lepszy niż zip dla Pythona 2 (ponieważ pozwala uniknąć niepotrzebnego tworzenia listy) i idealny dla wersji 2.6 lub niższej:Wynik dla wszystkich przypadków:
We wszystkich przypadkach:
Wyjaśnienie:
Jeśli spojrzymy na pomoc
dict
, widzimy, że wymaga ona różnych form argumentów:Optymalnym podejściem jest stosowanie iterowalności, przy jednoczesnym unikaniu tworzenia niepotrzebnych struktur danych. W Pythonie 2 zip tworzy niepotrzebną listę:
W Pythonie 3 odpowiednikiem byłoby:
a Python 3
zip
tworzy jedynie iterowalny obiekt:Ponieważ chcemy uniknąć tworzenia niepotrzebnych struktur danych, zwykle chcemy uniknąć Pythona 2
zip
(ponieważ tworzy niepotrzebną listę).Mniej wydajne alternatywy:
To wyrażenie generatora jest przekazywane do konstruktora dict:
lub równoważnie:
Oto koncept listy przekazywany konstruktorowi dykt:
W pierwszych dwóch przypadkach dodatkowa warstwa nieoperacyjnego (a więc niepotrzebnego) obliczenia jest umieszczana nad iterowalnym zamkiem błyskawicznym, aw przypadku zrozumienia listy niepotrzebnie tworzona jest dodatkowa lista. Spodziewałbym się, że wszystkie będą mniej wydajne, a na pewno nie bardziej.
Przegląd wydajności:
W 64-bitowym Pythonie 3.8.2 dostarczonym przez Nix na Ubuntu 16.04, uporządkowanym od najszybszego do najwolniejszego:
dict(zip(keys, values))
wygrywa nawet przy małych zestawach kluczy i wartości, ale w przypadku większych zestawów różnice w wydajności będą większe.Komentator powiedział:
Używamy,
min
ponieważ te algorytmy są deterministyczne. Chcemy poznać wydajność algorytmów w najlepszych możliwych warunkach.Jeśli system operacyjny zawiesza się z jakiegokolwiek powodu, nie ma to nic wspólnego z tym, co próbujemy porównać, dlatego musimy wykluczyć tego rodzaju wyniki z naszej analizy.
Gdybyśmy zastosowali
mean
, tego rodzaju zdarzenia znacznie zniekształcałyby nasze wyniki, a gdybyśmy zastosowali,max
otrzymalibyśmy tylko najbardziej ekstremalny wynik - ten, na który najprawdopodobniej wpłynie takie zdarzenie.Komentator mówi również:
Zakładam, że mamy na myśli
dict(zip(...
10k liczb losowych. To brzmi jak dość nietypowy przypadek użycia. To ma sens, że najbardziej bezpośrednie połączenia dominują w dużych zestawach danych i nie zdziwiłbym się, gdyby zawieszenia systemu dominowały, biorąc pod uwagę, ile czasu zajęłoby uruchomienie tego testu, dodatkowo wypaczając liczby. A jeśli użyjeszmean
lubmax
uznałbym twoje wyniki za bezsensowne.Zastosujmy bardziej realistyczny rozmiar w naszych najlepszych przykładach:
Widzimy tutaj, że
dict(zip(...
rzeczywiście działa szybciej dla większych zestawów danych o około 20%.źródło
dict(zip(headList, textList))
i 1,95 \ pm 0,030 mikrosekundy dla{k: v for k, v in zip(headList, textList)}
. Sugerowałbym ten pierwszy ze względu na czytelność i szybkość. Oczywiście jest to argument argumentu min () vs mean () dla timeit.min
wydaje się zły sposób na porównanie wydajności. Z pewnościąmean
i / lubmax
byłyby o wiele bardziej przydatne wskaźniki do rzeczywistego wykorzystania.dict
połączenie jest około 10% szybsze.Spróbuj tego:
W Pythonie 2 zużycie pamięci jest również bardziej ekonomiczne w porównaniu do
zip
.źródło
zip
jest już oszczędny w zużyciu pamięci. docs.python.org/3/library/functions.html#zip W rzeczywistości widać, żesix
używazip
Python 3 do zastępowaniaitertools.izip
w Python 2 pythonhosted.org/six .źródło
W języku Python ≥ 2.7 możesz także używać wyrażeń słownikowych:
źródło
Bardziej naturalnym sposobem jest użycie słownika
źródło
dict
obiekt, dlaczego tak jest ?, dzięki, stary.Jeśli potrzebujesz przekształcić klucze lub wartości przed utworzeniem słownika, możesz użyć wyrażenia generatora . Przykład:
Spójrz Kod jak Pythonista: Idiomatic Python .
źródło
w Pythonie 3.x chodzi o rozumienie nagrań
Więcej na temat rozumienia nagrań tutaj , przykład:
źródło
Dla tych, którzy potrzebują prostego kodu i nie są zaznajomieni z
zip
:Można to zrobić za pomocą jednego wiersza kodu:
źródło
List1
jest dłuższy niżList2
for n in range(len(List1))
jest anty-wzórNajlepszym rozwiązaniem jest nadal:
Przepisz to:
źródło
możesz użyć tego kodu poniżej:
Ale upewnij się, że długość list będzie taka sama. Jeśli długość nie jest taka sama. Następnie funkcja zip obróć dłuższą.
źródło
Miałem wątpliwości, gdy próbowałem rozwiązać problem związany z grafem. Problemem było to, że musiałem zdefiniować pustą listę przylegania i chciałem zainicjować wszystkie węzły z pustą listą, wtedy pomyślałem o tym, czy sprawdzę, czy jest wystarczająco szybki, to znaczy, czy warto wykonać operację zip zamiast prostej pary klucz-wartość przypisania. W większości przypadków czynnik czasu jest ważnym czynnikiem łamającym lód. Więc wykonałem operację timeit dla obu podejść.
Za n_nodes = 10 000 000 dostaję,
Iteracja: 2,825081646999024 Stenografia: 3,535717916001886
Iteracja: 5.051560923002398 Stenografia: 6,255070794999483
Iteracja: 6,52859034499852 Stenografia: 8,221581164998497
Iteracja: 8.683652416999394 Stenografia: 12.599181543999293
Iteracja: 11.587241565001023 Stenografia: 15,27298851100204
Iteracja: 14,816342867001367 Stenografia: 17.162912737003353
Iteracja: 16,645022411001264 Skrót: 19,976680120998935
Po pewnym punkcie widać wyraźnie, że podejście iteracyjne na n-tym kroku wyprzedza czas potrzebny na podejście skrótowe na n-1 kroku.
źródło
Oto także przykład dodania wartości listy do słownika
zawsze upewnij się, że Twój „klucz” (lista1) jest zawsze w pierwszym parametrze.
źródło
Rozwiązanie jako słownikowe z wyliczeniem:
Rozwiązanie jak dla pętli z wyliczeniem:
źródło
Możesz także spróbować z jedną listą, która jest kombinacją dwóch list;)
źródło
metoda bez funkcji zip
źródło