Czy istnieje sposób, aby mieć defaultdict(defaultdict(int))
następujący kod?
for x in stuff:
d[x.a][x.b] += x.c_int
d
musi być budowany ad hoc, w zależności od elementów x.a
i x.b
.
Mógłbym użyć:
for x in stuff:
d[x.a,x.b] += x.c_int
ale wtedy nie byłbym w stanie użyć:
d.keys()
d[x.a].keys()
python
collections
Jonathan
źródło
źródło
Odpowiedzi:
Tak jak to:
Argument
defaultdict
(w tym przypadku jestlambda: defaultdict(int)
) zostanie wywołany, gdy spróbujesz uzyskać dostęp do klucza, który nie istnieje. Wartość zwracana przez nią będzie ustawiony jako nową wartość tego klucza, czyli w naszym przypadku wartośćd[Key_doesnt_exist]
będziedefaultdict(int)
.Jeśli spróbujesz uzyskać dostęp do klucza z tego ostatniego defaultdict, tzn. Zwróci
d[Key_doesnt_exist][Key_doesnt_exist]
0, co jest wartością zwracaną argumentu z ostatniego defaultdict, tjint()
.źródło
defaultdict
(w tym przypadku jestlambda : defaultdict(int)
) zostanie wywołany, gdy spróbujesz uzyskać dostęp do klucza, który nie istnieje, a jego wartość zwrotna zostanie ustawiona jako nowa wartość tego klucza, co oznacza w naszym przypadku wartośćd[Key_dont_exist]
będziedefaultdict(int)
, a jeśli spróbujesz uzyskać dostęp do klucza z tego ostatniego defaultdict, tznd[Key_dont_exist][Key_dont_exist]
. zwróci 0, co jest wartością zwracaną z argumentu ostatniego,defaultdict
tj.int()
Mam nadzieję, że było to pomocne.defaultdict
powinna być funkcja.defaultdict(int)
jest słownikiem, natomiastlambda: defaultdict(int)
funkcja, która zwraca słownik.defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
Parametrem konstruktora defaultdict jest funkcja, która zostanie wywołana do budowania nowych elementów. Użyjmy lambda!
Od wersji Python 2.7 istnieje jeszcze lepsze rozwiązanie z użyciem Counter :
Niektóre funkcje dodatkowe
Aby uzyskać więcej informacji, zobacz PyMOTW - Kolekcje - Typy danych kontenerów i Dokumentacja Pythona - kolekcje
źródło
d = defaultdict(lambda : Counter())
raczej użyć zamiastd = defaultdict(lambda : defaultdict(int))
konkretnie rozwiązać problem, tak jak pierwotnie postawiono.d = defaultdict(Counter())
w tym przypadku możesz po prostu nie używać lambdaCounter
obiektu. To znaczy:d = defaultdict(Counter)
Uważam, że jest nieco bardziej elegancki w użyciu
partial
:Oczywiście jest to to samo, co lambda.
źródło
W celach informacyjnych można zaimplementować ogólną zagnieżdżoną
defaultdict
metodę fabryczną poprzez:Głębokość określa liczbę zagnieżdżonych słowników przed
default_factory
użyciem typu zdefiniowanego w . Na przykład:źródło
ndd = nested_defaultdict(dict) .... ndd['a']['b']['c']['d'] = 'e'
rzutyKeyError: 'b'
depth=0
, co może nie zawsze być pożądane, jeśli głębokość jest nieznana w momencie wywołania. Łatwo to naprawić, dodając linięif not depth: return default_factory()
na górze funkcji, choć prawdopodobnie jest to bardziej eleganckie rozwiązanie.Poprzednie odpowiedzi dotyczyły sposobu tworzenia poziomów dwupoziomowych lub n-poziomowych
defaultdict
. W niektórych przypadkach potrzebujesz nieskończonego:Stosowanie:
źródło
Inni poprawnie odpowiedzieli na twoje pytanie, jak uzyskać następujące działania:
Alternatywą byłoby użycie krotek do kluczy:
Zaletą tego podejścia jest to, że jest prosty i można go łatwo rozszerzyć. Jeśli potrzebujesz mapowania o głębokości trzech poziomów, po prostu użyj krotki z trzema przedmiotami dla klucza.
źródło