Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 递归地解析/转换结构化文本到字典_Python_Regex - Fatal编程技术网

Python 递归地解析/转换结构化文本到字典

Python 递归地解析/转换结构化文本到字典,python,regex,Python,Regex,是否有任何好的正则表达式/函数或包允许我们将缩进的结构化文本/数据解析到字典中?例如,我有这样的数据(可以有比我下面提到的更深的层次): xyz1:14 xyz2:35 xyz3:14 xyz4 sub1_xyz4 sub1_sub1_xyz4:45 sub2_sub1_xyz4:b1fawe sub2 xyz4:455 xyz5:2424 我想把它转换成字典,比如: { 'xyz1': '14', 'xyz2': '34', 'xyz3': '14', 'xy

是否有任何好的正则表达式/函数或包允许我们将缩进的结构化文本/数据解析到字典中?例如,我有这样的数据(可以有比我下面提到的更深的层次):

xyz1:14
xyz2:35
xyz3:14
xyz4
sub1_xyz4
sub1_sub1_xyz4:45
sub2_sub1_xyz4:b1fawe
sub2 xyz4:455
xyz5:2424
我想把它转换成字典,比如:

{
    'xyz1': '14',
    'xyz2': '34',
    'xyz3': '14',
    'xyz4': {
        'sub1_xyz4': {
            'sub1_sub1_xyz4': '45',
            'sub2_sub1_xyz4': 'b1fawe',
        },
        'sub2_xyz4': '455'
    },
    'xyz5': '2424'
}
我尝试了以下方法,但未能始终如一。我觉得在尝试管理缩进/子属性时,有一个非常好的递归(以便它可以处理未知深度)函数。有什么建议吗

def parse_output(value, indent=0):
    parsed_dict = dict()
    if indent > 0:
       for i in re.split('\n(?!\s{,%d})' % (indent - 1), value):
            print("split value is: : ", i)
            if '\n' not in i:
                iter_val = iter(list(map(lambda x: x.strip(), re.split(' : ', i))))
                parsed_dict = {**parsed_dict, **dict(zip(iter_val, iter_val))}
            else:
                parse_bearer_info(re.split('\n', i, 1)[1])
                iter_val = iter(list(map(lambda x: x.strip(), re.split('\n', i, 1))))
                parsed_dict = {**parsed_dict, **dict(zip(iter_val, iter_val))}
    else:
        for i in re.split('\n(?!\s+)', value):
            #print("iteration value is: ", i)
            if '\n' not in i:
                iter_val = iter(list(map(lambda x: x.strip(), re.split(' : ', i))))
                parsed_dict = {**parsed_dict, **dict(zip(iter_val, iter_val))}
            else:
                #print(re.split('\n', i, 1))
                #out = parse_bearer_info(re.split('\n', i, 1)[1], 4)
                iter_val = iter(list(map(lambda x: x.strip(), re.split('\n', i, 1))))
                parsed_dict = {**parsed_dict, **dict(zip(iter_val, iter_val))}

    return parsed_dict

您可能可以递归地执行此操作,但因为您只需要跟踪单个缩进级别,所以您可以只保留当前对象的堆栈。将键添加到堆栈中的最后一项。当值为空时,添加一个新字典并将其推送到堆栈中。缩进减少时,从堆栈中弹出

比如:

res = {}
stack = [res]
cur_indent = 0
for line in s.split('\n'):
    indent = len(line) - len(line.lstrip())
    if (indent < cur_indent):               # backing out
        stack.pop()
        cur_indent = indent
    else:
        cur_indent = indent

    vals = line.replace(" ", "").split(':')

    current_dict = stack[-1]
    if(len(vals) == 2):                    
        current_dict[vals[0]] = vals[1]
    else:                                   # no value, must be a new level
        current_dict[vals[0]] = {}
        stack.append(current_dict[vals[0]])

您可以将
itertools.groupby
与递归一起使用:

import itertools, re, json
_data = [re.split('\s+:\s+', i) for i in filter(None, content.split('\n'))]
def group_data(d):
  _d = [[a, list(b)] for a, b in itertools.groupby(d, key=lambda x:bool(x[-1]) and not x[0].startswith(' '))]
  _new_result = {}
  for a, b in _d:
    if a:
      _new_result.update(dict([[c, _d] for c, [_d] in b]))
    else:
      _new_result[b[0][0]] = group_data([[c[2:], _d] for c, _d in b[1:]])
  return _new_result

print(json.dumps(group_data([[a, b] for a, *b in _data]), indent=4))
输出:

{
 "xyz1": "14",
 "xyz2": "35",
 "xyz3": "14",
 "xyz4": {
    "sub1_xyz4": {
        "sub1_sub1_xyz4": "45",
        "sub2_sub1_xyz4": "b1fawe"
      },
      "sub2 xyz4": "455"
   },
  "xyz5": "2424"
}
其中
内容
为:

xyz1                      : 14
xyz2                      : 35
xyz3                      : 14
xyz4
  sub1_xyz4
    sub1_sub1_xyz4        : 45
    sub2_sub1_xyz4        : b1fawe
  sub2 xyz4               : 455
xyz5                      : 2424

谢谢,这很有效,但我想我在描述中没有提到这一点,但缩进级别可以比我在描述中提到的更进一步。还是很好。我会使用缩进级别来跟踪当前和未来的缩进级别。
xyz1                      : 14
xyz2                      : 35
xyz3                      : 14
xyz4
  sub1_xyz4
    sub1_sub1_xyz4        : 45
    sub2_sub1_xyz4        : b1fawe
  sub2 xyz4               : 455
xyz5                      : 2424