파이썬을 사용하여 구분된 문자열 목록을 트리/중첩 사전으로 변환 (convert a list of delimited strings to a tree/nested dict, using python)


문제 설명

파이썬을 사용하여 구분된 문자열 목록을 트리/중첩 사전으로 변환 (convert a list of delimited strings to a tree/nested dict, using python)

I am trying to convert a list of dot‑separated strings, e.g.

['one.two.three.four', 'one.six.seven.eight', 'five.nine.ten', 'twelve.zero']

into a tree (nested lists or dicts ‑ anything that is easy to walk through). The real data happens to have 1 to 4 dot‑separated parts  of different length and has 2200 records in total. My actual goal is to fill in the set of 4 QComboBox'es with this data, in manner that the 1st QComboBox is filled with first set items ['one', 'five', 'twelve'] (no duplicates). Then depending on the chosen item, the 2nd QComboBox is filled with its related items: for 'one' it would be: ['two', 'six'], and so on, if there's another nested level.

So far I've got a working list ‑> nested dicts solution, but it's horribly slow, since I use regular dict(). And I seem to have a trouble to redesign it to a defaultdict in a way to easily work out filling the ComboBoxes properly.

My current code:

def list2tree(m):
    tmp = {}
    for i in range(len(m)):
        if m.count('.') == 0:
            return m
        a = m.split('.', 1)
        try:
            tmp[a[0]].append(list2tree(a[1]))
        except (KeyError, AttributeError):
            tmp[a[0]] = list2tree(a[1])
    return tmp

main_dict = {}
i = 0
for m in methods:
    main_dict = list2tree(m)
    i += 1
    if (i % 100) == 0: print i, len(methods)
print main_dict, i, len(methods)

참조 솔루션

방법 1:

ls = ['one.two.three.four', 'one.six.seven.eight', 'five.nine.ten', 'twelve.zero']
tree = {}

for item in ls:
    t = tree
    for part in item.split('.'):
        t = t.setdefault(part, {})

Result:

{
 "twelve": {
  "zero": {}
 }, 
 "five": {
  "nine": {
   "ten": {}
  }
 }, 
 "one": {
  "six": {
   "seven": {
    "eight": {}
   }
  }, 
  "two": {
   "three": {
    "four": {}
   }
  }
 }
}

방법 2:

While this is beyond the reach of the original question, some comments mentioned a form of this algorithm that incorporates values. I came up with this to that end:

def dictionaryafy(self, in_dict):
    tree = {}
    for key, value in in_dict.items():
        t = tree
        parts = key.split(".")
        for part in parts[:‑1]:
            t = t.setdefault(part, {})
        t[parts[‑1]] = value
    return tree

(by python_headgeorgLucas Niewohner)

참조 문서

  1. convert a list of delimited strings to a tree/nested dict, using python (CC BY‑SA 3.0/4.0)

#defaultdict #Python #Dictionary #pyside






관련 질문

많이 중첩 된 defaultdict에서 물건을 계산하는보다 Pythonic 방법 (More Pythonic way of counting things in a heavily nested defaultdict)

GAE ndb에서 산세척 (Pickling on GAE ndb)

파이썬을 사용하여 구분된 문자열 목록을 트리/중첩 사전으로 변환 (convert a list of delimited strings to a tree/nested dict, using python)

Python에서 defaultdict 또는 dict를 Ordereddict로 변환할 수 있습니까? (Can I convert a defaultdict or dict to an ordereddict in Python?)

기본 사전의 각 키를 고유한 CSV 파일에 쓰기 (Writing each key in a default dict to a unique csv file)

TypeError: 첫 번째 인수는 호출 가능해야 합니다. defaultdict (TypeError: first argument must be callable, defaultdict)

defaultdict(list)를 Pandas DataFrame으로 변환하는 방법 (How to convert a defaultdict(list) to Pandas DataFrame)

여러 매개변수가 있는 defaultdict (defaultdict with multiple parameters)

함께 사용되는 Defaultdict 및 람다 함수 (Defaultdict and lambda function used together)

클래스/유형을 포함하지 않고 중첩된 defaultdict를 인쇄하는 방법은 무엇입니까? (How to print a nested defaultdict without including the class/type?)

dict에서 빈 세트를 제거하는 간단한 방법 (Simple way to remove empty sets from dict)

특정 키를 포함하는 많은 defaultdicts의 값 가져오기 (Getting the values of many defaultdicts that contains a certain key)







코멘트