[PYTHON] 파이썬에서 들여 쓰기 된 텍스트 파일에서 나무 / 깊게 중첩 된 dict 만들기
PYTHON파이썬에서 들여 쓰기 된 텍스트 파일에서 나무 / 깊게 중첩 된 dict 만들기
기본적으로 파일을 반복하고 각 줄의 내용을 깊게 중첩 된 dict에 넣고 싶습니다. 구조는 각 줄의 시작 부분에있는 공백의 크기로 정의됩니다.
근본적으로 목표는 다음과 같은 것을 취하는 것입니다 :
a
b
c
d
e
그리고 이것을 다음과 같이 바꾸십시오 :
{"a":{"b":"c","d":"e"}}
아니면 이거:
apple
colours
red
yellow
green
type
granny smith
price
0.10
이것으로 :
{"apple":{"colours":["red","yellow","green"],"type":"granny smith","price":0.10}
그래서 파이썬의 JSON 모듈로 보내서 JSON을 만들 수 있습니다.
지금 나는 그런 단계에서 dict과리스트를 만들려고 노력하고있다 :
기타
이 목록은 내가 마지막으로 딕테이션에 넣은 위치를 보여주는 '빵 부스러기'와 같은 역할을합니다.
이렇게하려면 목록을 반복하고 dict [ "a"] [ "e"] [ "f"]와 같은 것을 생성하여 마지막 딕트를 얻는 방법이 필요합니다. 누군가가 만들었던 AutoVivification 클래스를 살펴 보았지만 매우 유용하게 보입니다.
다음 함수를 생각해 냈지만 작동하지 않습니다.
def get_nested(dict,array,i):
if i != None:
i += 1
if array[i] in dict:
return get_nested(dict[array[i]],array)
else:
return dict
else:
i = 0
return get_nested(dict[array[i]],array)
도와 주셔서 감사합니다!
(나머지 매우 극히 불완전한 코드는 여기에 있습니다 :)
#Import relevant libraries
import codecs
import sys
#Functions
def stripped(str):
if tab_spaced:
return str.lstrip('\t').rstrip('\n\r')
else:
return str.lstrip().rstrip('\n\r')
def current_ws():
if whitespacing == 0 or not tab_spaced:
return len(line) - len(line.lstrip())
if tab_spaced:
return len(line) - len(line.lstrip('\t\n\r'))
def get_nested(adict,anarray,i):
if i != None:
i += 1
if anarray[i] in adict:
return get_nested(adict[anarray[i]],anarray)
else:
return adict
else:
i = 0
return get_nested(adict[anarray[i]],anarray)
#initialise variables
jsondict = {}
unclosed_tags = []
debug = []
vividfilename = 'simple.vivid'
# vividfilename = sys.argv[1]
if len(sys.argv)>2:
jsfilename = sys.argv[2]
else:
jsfilename = vividfilename.split('.')[0] + '.json'
whitespacing = 0
whitespace_array = [0,0]
tab_spaced = False
#open the file
with codecs.open(vividfilename,'rU', "utf-8-sig") as vividfile:
for line in vividfile:
#work out how many whitespaces at start
whitespace_array.append(current_ws())
#For first line with whitespace, work out the whitespacing (eg tab vs 4-space)
if whitespacing == 0 and whitespace_array[-1] > 0:
whitespacing = whitespace_array[-1]
if line[0] == '\t':
tab_spaced = True
#strip out whitespace at start and end
stripped_line = stripped(line)
if whitespace_array[-1] == 0:
jsondict[stripped_line] = ""
unclosed_tags.append(stripped_line)
if whitespace_array[-2] < whitespace_array[-1]:
oldnested = get_nested(jsondict,whitespace_array,None)
print oldnested
# jsondict.pop(unclosed_tags[-1])
# jsondict[unclosed_tags[-1]]={stripped_line:""}
# unclosed_tags.append(stripped_line)
print jsondict
print unclosed_tags
print jsondict
print unclosed_tags
해결법
-
==============================
1.다음은 재귀 적 솔루션입니다. 먼저 다음과 같이 입력을 변환합니다.
다음은 재귀 적 솔루션입니다. 먼저 다음과 같이 입력을 변환합니다.
입력:
person: address: street1: 123 Bar St street2: city: Madison state: WI zip: 55555 web: email: boo@baz.com
첫 번째 단계 출력 :
[{'name':'person','value':'','level':0}, {'name':'address','value':'','level':1}, {'name':'street1','value':'123 Bar St','level':2}, {'name':'street2','value':'','level':2}, {'name':'city','value':'Madison','level':2}, {'name':'state','value':'WI','level':2}, {'name':'zip','value':55555,'level':2}, {'name':'web','value':'','level':1}, {'name':'email','value':'boo@baz.com','level':2}]
분할 ( ':') 및 선행 탭의 수를 계산하여 쉽게 수행 할 수 있습니다.
def tab_level(astr): """Count number of leading tabs in a string """ return len(astr)- len(astr.lstrip('\t'))
그런 다음 첫 번째 단계 출력을 다음 함수에 제공합니다.
def ttree_to_json(ttree,level=0): result = {} for i in range(0,len(ttree)): cn = ttree[i] try: nn = ttree[i+1] except: nn = {'level':-1} # Edge cases if cn['level']>level: continue if cn['level']<level: return result # Recursion if nn['level']==level: dict_insert_or_append(result,cn['name'],cn['value']) elif nn['level']>level: rr = ttree_to_json(ttree[i+1:], level=nn['level']) dict_insert_or_append(result,cn['name'],rr) else: dict_insert_or_append(result,cn['name'],cn['value']) return result return result
어디에:
def dict_insert_or_append(adict,key,val): """Insert a value in dict at key if one does not exist Otherwise, convert value to list and append """ if key in adict: if type(adict[key]) != list: adict[key] = [adict[key]] adict[key].append(val) else: adict[key] = val
-
==============================
2.다음 코드는 블록 들여 쓰기 된 파일을 가져 와서 XML 트리로 변환합니다. 이:
다음 코드는 블록 들여 쓰기 된 파일을 가져 와서 XML 트리로 변환합니다. 이:
foo bar baz ban bal
...가됩니다 :
<cmd>foo</cmd> <cmd>bar</cmd> <block> <name>baz</name> <cmd>ban</cmd> <cmd>bal</cmd> </block>
기본 기술은 다음과 같습니다.
그래서:
from lxml import builder C = builder.ElementMaker() def indent(line): strip = line.lstrip() return len(line) - len(strip), strip def parse_blockcfg(data): top = current_block = C.config() stack = [] current_indent = 0 lines = data.split('\n') while lines: line = lines.pop(0) i, line = indent(line) if i==current_indent: pass elif i > current_indent: # we've gone down a level, convert the <cmd> to a block # and then save the current ident and block to the stack prev.tag = 'block' prev.append(C.name(prev.text)) prev.text = None stack.insert(0, (current_indent, current_block)) current_indent = i current_block = prev elif i < current_indent: # we've gone up one or more levels, pop the stack # until we find out which level and return to it found = False while stack: parent_indent, parent_block = stack.pop(0) if parent_indent==i: found = True break if not found: raise Exception('indent not found in parent stack') current_indent = i current_block = parent_block prev = C.cmd(line) current_block.append(prev) return top
-
==============================
3.우선, 배열과 dict는 파이썬에서 예약어이기 때문에 변수 이름으로 사용하지 말고 다시 사용하면 모든 종류의 혼란을 겪을 수 있습니다.
우선, 배열과 dict는 파이썬에서 예약어이기 때문에 변수 이름으로 사용하지 말고 다시 사용하면 모든 종류의 혼란을 겪을 수 있습니다.
좋아요. 올바르게 구하면 텍스트 파일에 트리가 있습니다. 부모가 들여 쓰기로 표시되며 실제 트리 구조를 복구하려고합니다. 권리?
다음은 유효한 윤곽선처럼 보입니까? 현재 코드를 컨텍스트에 넣는 데 어려움이 있기 때문입니다.
result = {} last_indentation = 0 for l in f.xreadlines(): (c, i) = parse(l) # create parse to return character and indentation if i==last_indentation: # sibling to last elif i>last_indentation: # child to last else: # end of children, back to a higher level
그렇다면 귀하의 목록은 현재 부모입니다. 사실 그것은 맞습니다. 그러나 나는 문자 그대로 편지가 아닌 작성한 사전을 계속 지적 할 것입니다.
여기서 몇 가지 일을 시작하는거야.
result = {} parents = {} last_indentation = 1 # start with 1 so 0 is the root of tree parents[0] = result for l in f.xreadlines(): (c, i) = parse(l) # create parse to return character and indentation if i==last_indentation: new_el = {} parents[i-1][c] = new_el parents[i] = new_el elif i>last_indentation: # child to last else: # end of children, back to a higher level
-
==============================
4.다음은 중첩 된 Node 객체의 복합 구조에 기반한 객체 지향 접근 방식입니다.
다음은 중첩 된 Node 객체의 복합 구조에 기반한 객체 지향 접근 방식입니다.
입력:
indented_text = \ """ apple colours red yellow green type granny smith price 0.10 """
Node 클래스
class Node: def __init__(self, indented_line): self.children = [] self.level = len(indented_line) - len(indented_line.lstrip()) self.text = indented_line.strip() def add_children(self, nodes): childlevel = nodes[0].level while nodes: node = nodes.pop(0) if node.level == childlevel: # add node as a child self.children.append(node) elif node.level > childlevel: # add nodes as grandchildren of the last child nodes.insert(0,node) self.children[-1].add_children(nodes) elif node.level <= self.level: # this node is a sibling, no more children nodes.insert(0,node) return def as_dict(self): if len(self.children) > 1: return {self.text: [node.as_dict() for node in self.children]} elif len(self.children) == 1: return {self.text: self.children[0].as_dict()} else: return self.text
텍스트를 구문 분석하려면 먼저 루트 노드를 만듭니다. 그런 다음 텍스트에서 빈 행을 제거하고 모든 행에 대해 Node 인스턴스를 만든 다음 루트 노드의 add_children 메소드에 전달합니다.
root = Node('root') root.add_children([Node(line) for line in indented_text.splitlines() if line.strip()]) d = root.as_dict()['root'] print(d)
결과:
{'apple': [ {'colours': ['red', 'yellow', 'green']}, {'type': 'granny smith'}, {'price': '0.10'}] }
들여 쓰기 된 텍스트를 인수로 사용하여 Node의 생성자를 호출하면되는 단계에서이 작업을 수행 할 수 있어야한다고 생각합니다.
from https://stackoverflow.com/questions/17858404/creating-a-tree-deeply-nested-dict-from-an-indented-text-file-in-python by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] MultiIndex pandas DataFrame의 하위 집합을 업데이트하는 방법 (0) | 2018.11.27 |
---|---|
[PYTHON] Python에서 시스템 폴더 위치 찾기 (0) | 2018.11.27 |
[PYTHON] 통계적 유의성과 판다 열 상관 관계 (0) | 2018.11.27 |
[PYTHON] Gmail 및 Python을 통해 이메일 보내기 (0) | 2018.11.27 |
[PYTHON] JavaScript에서 파이썬 호출하기 (0) | 2018.11.27 |