[python] 파이썬 : defaultdict의 defaultdict?

defaultdict(defaultdict(int))다음 코드를 작동시킬 수 있는 방법이 있습니까?

for x in stuff:
    d[x.a][x.b] += x.c_int

d요구에 따라 임시을 구축 할 x.ax.b요소.

나는 사용할 수있다 :

for x in stuff:
    d[x.a,x.b] += x.c_int

그러나 나는 사용할 수 없었습니다 :

d.keys()
d[x.a].keys()



답변

예, 이런 식으로 :

defaultdict(lambda: defaultdict(int))

존재하지 않는 키에 액세스하려고 하면 defaultdict(이 경우는 lambda: defaultdict(int)) 의 인수 가 호출됩니다. 그것의 반환 값은이 키의 새로운 값으로 설정 될 것이며,이 경우 우리의 값은 d[Key_doesnt_exist]입니다 defaultdict(int).

이 마지막 defaultdict에서 키에 액세스하려고하면, 즉 d[Key_doesnt_exist][Key_doesnt_exist]0이 리턴됩니다 int(). 즉, 마지막 defaultdict 인수의 리턴 값입니다 .


답변

defaultdict 생성자에 대한 매개 변수는 새 요소를 빌드하기 위해 호출되는 함수입니다. 람다를 사용하자!

>>> from collections import defaultdict
>>> d = defaultdict(lambda : defaultdict(int))
>>> print d[0]
defaultdict(<type 'int'>, {})
>>> print d[0]["x"]
0

Python 2.7부터 Counter를 사용 하는 더 나은 솔루션이 있습니다 .

>>> from collections import Counter
>>> c = Counter()
>>> c["goodbye"]+=1
>>> c["and thank you"]=42
>>> c["for the fish"]-=5
>>> c
Counter({'and thank you': 42, 'goodbye': 1, 'for the fish': -5})

일부 보너스 기능

>>> c.most_common()[:2]
[('and thank you', 42), ('goodbye', 1)]

자세한 정보는 PyMOTW-콜렉션-컨테이너 데이터 유형Python 문서-콜렉션을 참조하십시오.


답변

사용하는 것이 조금 더 우아하다는 것을 알았습니다 partial.

import functools
dd_int = functools.partial(defaultdict, int)
defaultdict(dd_int)

물론 이것은 람다와 동일합니다.


답변

참고로 다음을 defaultdict통해 일반 중첩 팩토리 메소드 를 구현할 수 있습니다 .

from collections import defaultdict
from functools import partial
from itertools import repeat


def nested_defaultdict(default_factory, depth=1):
    result = partial(defaultdict, default_factory)
    for _ in repeat(None, depth - 1):
        result = partial(defaultdict, result)
    return result()

깊이는에 정의 된 유형 default_factory이 사용 되기 전에 중첩 된 사전의 수를 정의합니다 . 예를 들면 다음과 같습니다.

my_dict = nested_defaultdict(list, 3)
my_dict['a']['b']['c'].append('e')


답변

이전 답변에서는 2 단계 또는 n 단계를 만드는 방법을 설명했습니다 defaultdict. 어떤 경우에는 무한한 것을 원합니다.

def ddict():
    return defaultdict(ddict)

용법:

>>> d = ddict()
>>> d[1]['a'][True] = 0.5
>>> d[1]['b'] = 3
>>> import pprint; pprint.pprint(d)
defaultdict(<function ddict at 0x7fcac68bf048>,
            {1: defaultdict(<function ddict at 0x7fcac68bf048>,
                            {'a': defaultdict(<function ddict at 0x7fcac68bf048>,
                                              {True: 0.5}),
                             'b': 3})})


답변

다른 사람들은 다음을 작동시키는 방법에 대한 귀하의 질문에 올바르게 대답했습니다.

for x in stuff:
    d[x.a][x.b] += x.c_int

다른 방법은 키에 튜플을 사용하는 것입니다.

d = defaultdict(int)
for x in stuff:
    d[x.a,x.b] += x.c_int
    # ^^^^^^^ tuple key

이 방법의 장점은 간단하고 쉽게 확장 할 수 있다는 것입니다. 3 단계 깊이의 매핑이 필요한 경우 키에 3 개의 항목 튜플을 사용하십시오.


답변