기본 딕트의 중첩 기본 딕트
기본 명령어도 기본 명령어로 만들 수 있는 방법이 있습니까?(즉, 무한 수준 재귀 기본 명령?)
저는 다음과 같은 일을 할 수 있습니다.
x = defaultdict(...stuff...)
x[0][1][0]
{}
할 수 있어요.x = defaultdict(defaultdict)
하지만 그건 두 번째 수준에 불과합니다.
x[0]
{}
x[0][0]
KeyError: 0
이것을 할 수 있는 요리법들이 있습니다.하지만 단순히 일반적인 기본 명령 인수를 사용하여 수행할 수 있습니까?
이것은 무한 수준의 재귀 기본값 딕트를 수행하는 방법을 묻는 것이므로 파이썬: 기본값 딕트?와 구별됩니다. 기본값 딕트는 2단계 기본값 딕트를 수행하는 방법이었습니다.
저는 아마 그냥 다발 패턴을 사용하게 될 것입니다. 하지만 제가 이걸 어떻게 하는지 모른다는 것을 알았을 때, 그것은 저를 흥미롭게 했습니다.
여기에 있는 다른 답변은 다음과 같은 방법을 사용할 수 있습니다.defaultdict
"무한히 많은" 것을 포함하는.defaultdict
하지만 그들은 단순히 2개의 깊이의 기본 명령을 갖는 것이 당신의 초기 요구였을 것이라고 생각하는 것을 해결하지 못합니다.
다음을 찾고 있었을 수 있습니다.
defaultdict(lambda: defaultdict(dict))
이 구성을 선호하는 이유는 다음과 같습니다.
- 이것은 재귀적 해결책보다 더 명확하기 때문에 독자들이 더 이해할 수 있을 것입니다.
- 이렇게 하면 의 "리프"가 활성화됩니다.
defaultdict
사전 이외의 것이 되는 것, 예:defaultdict(lambda: defaultdict(list))
또는defaultdict(lambda: defaultdict(set))
임의의 수준 수:
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)
그렇게 하는 데는 멋진 묘기가 있습니다.
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': {}}
저는 앤드류의 대답을 여기에 근거로 삼았습니다.json 또는 기존 dict에서 nester default dict로 데이터를 로드하려는 경우 다음 예를 참조하십시오.
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
다음은 임의 중첩 깊이에 대한 임의 기본값 딕트에 대한 함수입니다.
(Can't pickle default dict의 교차 게시)
def wrap_defaultdict(instance, times=1):
"""Wrap an instance an arbitrary number of `times` to create nested defaultdict.
Parameters
----------
instance - list, dict, int, collections.Counter
times - the number of nested keys above `instance`; if `times=3` dd[one][two][three] = instance
Notes
-----
using `x.copy` allows pickling (loading to ipyparallel cluster or pkldump)
- thanks https://stackoverflow.com/questions/16439301/cant-pickle-defaultdict
"""
from collections import defaultdict
def _dd(x):
return defaultdict(x.copy)
dd = defaultdict(instance)
for i in range(times-1):
dd = _dd(dd)
return dd
그러나 Chris W 답변을 기반으로 유형 주석 문제를 해결하기 위해 자세한 유형을 정의하는 공장 함수로 만들 수 있습니다.예를 들어, 이것이 제가 이 질문을 조사할 때의 문제에 대한 최종 해결책입니다.
def frequency_map_factory() -> dict[str, dict[str, int]]:
"""
Provides a recorder of: per X:str, frequency of Y:str occurrences.
"""
return defaultdict(lambda: defaultdict(int))
여기 재귀적 기본 딕트를 일반 딕트로 변환하는 재귀 함수가 있습니다.
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, {})
@nucklehead의 응답은 JSON의 어레이도 처리하도록 확장할 수 있습니다.
def nested_dict(existing=None, **kwargs):
if existing is None:
existing = defaultdict()
if isinstance(existing, list):
existing = [nested_dict(val) for val in existing]
if not isinstance(existing, dict):
return existing
existing = {key: nested_dict(val) for key, val in existing.items()}
return defaultdict(nested_dict, existing, **kwargs)
다음은 멀티프로세싱과 함께 작동하고 중첩 종료를 허용하는 @Stanislav의 답변과 유사한 솔루션입니다.
from collections import defaultdict
from functools import partial
class NestedDD(defaultdict):
def __init__(self, n, *args, **kwargs):
self.n = n
factory = partial(build_nested_dd, n=n - 1) if n > 1 else int
super().__init__(factory, *args, **kwargs)
def __repr__(self):
return repr(dict(self))
def build_nested_dd(n):
return NestedDD(n)
언급URL : https://stackoverflow.com/questions/19189274/nested-defaultdict-of-defaultdict
'programing' 카테고리의 다른 글
동적 프로그래밍 - 최대 사각형 블록 (0) | 2023.07.08 |
---|---|
CREATE FUNCTION에서 SQL 오류 발생(1064)(42000) (0) | 2023.07.08 |
Vuex 스토어 내에서 일반 작업을 수행하는 가장 좋은 방법은 무엇입니까? (0) | 2023.07.08 |
'System' 유형입니다.개체'가 참조되지 않는 어셈블리에 정의되었습니다. (0) | 2023.07.08 |
mongodb 또는 cassandra를 사용한 공간 데이터 (0) | 2023.07.08 |