defaultdict를 defaultdict의 기본값으로 만드는 방법이 있습니까? (예 : 무한 레벨 재귀 defaultdict?)
할 수 있기를 원합니다 :
x = defaultdict(...stuff...)
x[0][1][0]
{}
그래서 할 수는 x = defaultdict(defaultdict)
있지만 두 번째 수준 일뿐입니다.
x[0]
{}
x[0][0]
KeyError: 0
이를 수행 할 수있는 레시피가 있습니다. 그러나 일반적인 defaultdict 인수를 사용하여 간단하게 수행 할 수 있습니까?
이것은 무한 레벨 재귀 defaultdict를 수행하는 방법을 묻기 때문에 Python과 다릅니다 : defaultdict의 defaultdict? , 이것은 두 가지 수준의 기본 결정을 수행하는 방법이었습니다.
아마도 다발 패턴을 사용하게 될 것입니다 .
답변
임의의 수의 레벨의 경우 :
def rec_dd():
return defaultdict(rec_dd)
>>> x = rec_dd()
>>> x['a']['b']['c']['d']
defaultdict(<function rec_dd at 0x7f0dcef81500>, {})
>>> print json.dumps(x)
{"a": {"b": {"c": {"d": {}}}}}
물론 람다 로이 작업을 수행 할 수도 있지만 람다는 읽기 쉽지 않습니다. 어쨌든 다음과 같습니다.
rec_dd = lambda: defaultdict(rec_dd)
답변
여기에있는 다른 답변 defaultdict
은 “무한한 많은”을 포함하는를 만드는 방법을 알려 defaultdict
주지만, 처음에는 두 가지 깊이의 기본 결정을 내릴 필요가 있다고 생각하는 것을 다루지 않습니다.
당신은 찾고 있었을 것입니다 :
defaultdict(lambda: defaultdict(dict))
이 구성을 선호하는 이유는 다음과 같습니다.
- 재귀 솔루션보다 더 명확하므로 독자가 이해할 수 있습니다.
- 이것은의 “잎”수
defaultdict
사전이 아닌 다른 일, 예를 들어, : 할defaultdict(lambda: defaultdict(list))
또는defaultdict(lambda: defaultdict(set))
답변
이를위한 멋진 트릭이 있습니다.
tree = lambda: defaultdict(tree)
그런 다음로을 만들 수 x
있습니다 x = tree()
.
답변
BrenBarn의 솔루션과 유사하지만 변수 이름이 tree
두 번 포함되어 있지 않으므로 변수 사전을 변경 한 후에도 작동합니다.
tree = (lambda f: f(f))(lambda a: (lambda: defaultdict(a(a))))
그런 다음 각각의 새로운 만들 수 x
와를 x = tree()
.
를 들어 def
버전, 우리는 경우 기존 인스턴스가 작동 중지 결함에서 데이터 구조를 보호하기 위해 함수 클로저 범위를 사용할 수있는 tree
이름이 반등이다. 다음과 같이 보입니다 :
from collections import defaultdict
def tree():
def the_tree():
return defaultdict(the_tree)
return the_tree()
답변
또한 무한 중첩 및 올바른 형식을 지원하는 더 많은 OOP 스타일 구현을 제안합니다 repr
.
class NestedDefaultDict(defaultdict):
def __init__(self, *args, **kwargs):
super(NestedDefaultDict, self).__init__(NestedDefaultDict, *args, **kwargs)
def __repr__(self):
return repr(dict(self))
용법:
my_dict = NestedDefaultDict()
my_dict['a']['b'] = 1
my_dict['a']['c']['d'] = 2
my_dict['b']
print(my_dict) # {'a': {'b': 1, 'c': {'d': 2}}, 'b': {}}
답변
다음은 재귀 기본 dict를 일반 dict로 변환하는 재귀 함수입니다.
def defdict_to_dict(defdict, finaldict):
# pass in an empty dict for finaldict
for k, v in defdict.items():
if isinstance(v, defaultdict):
# new level created and that is the new value
finaldict[k] = defdict_to_dict(v, {})
else:
finaldict[k] = v
return finaldict
defdict_to_dict(my_rec_default_dict, {})
답변
나는 앤드류의 대답에 근거했습니다 . json 또는 기존 dict에서 nester defaultdict로 데이터를로드하려는 경우 다음 예제를 참조하십시오.
def nested_defaultdict(existing=None, **kwargs):
if existing is None:
existing = {}
if not isinstance(existing, dict):
return existing
existing = {key: nested_defaultdict(val) for key, val in existing.items()}
return defaultdict(nested_defaultdict, existing, **kwargs)
https://gist.github.com/nucklehead/2d29628bb49115f3c30e78c071207775