嵌套字典的递归函数

时间:2018-09-21 07:01:56

标签: python dictionary recursion

我有一个asn格式的文本文件,现在在此示例中在此处编写我自己的解析器,它首先为Order创建一个字典,然后进入各项,然后查看值是否不是字典,Dictionary文件中已被识别并保存在seq_list中。现在,我需要编写一个递归函数,该函数位于所有字典中并创建嵌套字典。

    import re
    ee='\
    Module-order DEFINITIONS AUTOMATIC TAGS ::=\
    BEGIN\
    Order ::= SEQUENCE {\
    header Order-header\
     }\
    Order-header ::= SEQUENCE {\
    reference NumericString (SIZE (12)),\
    date NumericString (SIZE (8)) -- MMDDYYYY --\
    }END'

    seq_list=['Order','Order-header']

    condition='Order ::= SEQUENCE {\
    header Order-header\
     }'
    def rec_fn():
        ee=ee.lower()
        ee=ee.replace('\n','')
        for i in condition:
            # Removes emty items
            i=i.split(' ')
            k.append(filter(None, i))
        for index_content,content in enumerate(k):
            for index,value in enumerate(content[1:]):
                new_value=value.replace(',','')
                if new_value in seq_list:
                    # will have the contents of all the items of the new  
                    # dictionary found.
                    reg_value=re.findall(r'{0}\s*::=\s*sequence(.*?)(::=|end)'.format(new_value),ee)

sample.asn

       ee=''' Module-order DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
Order ::= SEQUENCE {
header Order-header,
items SEQUENCE OF Order-line }
Order-header ::= SEQUENCE {
reference NumericString (SIZE (12)),
date NumericString (SIZE (8)) -- MMDDYYYY --,
client Client,
payment Payment-method }
Client ::= SEQUENCE {
name PrintableString (SIZE (1..20)),
street PrintableString (SIZE (1..50)) OPTIONAL,
postcode NumericString (SIZE (5)),
town PrintableString (SIZE (1..30)),
country PrintableString (SIZE (1..20)) DEFAULT "France" }
Payment-method ::= CHOICE {
check NumericString (SIZE (15)),
credit-card Credit-card,
cash NULL }
Credit-card ::= SEQUENCE {
type Card-type,
number NumericString (SIZE (20)),
expiry-date NumericString (SIZE (6)) -- MMYYYY -- }
Card-type ::= ENUMERATED {cb(0), visa(1), eurocard(2), diners(3), american-express(4)}END

1 个答案:

答案 0 :(得分:0)

您可以使用以下递归函数:

import re
def rec_fn(asn, key):
    def build_definitions(mapping, key, sequence_only=False):
        if not sequence_only and (key,) in mapping:
            key = (key,)
            is_choice = True
        else:
            is_choice = False
        if isinstance(mapping[key], dict):
            definitions = {}
            for variable, definition in mapping[key].items():
                if definition in mapping or (definition,) in mapping:
                    definitions[variable] = build_definitions(mapping, definition, sequence_only=is_choice)
                else:
                    definitions[variable] = definition
            return definitions
        else:
            return mapping[key]
    mapping = {}
    for name, type, definition in re.findall(r'([A-Za-z-]+)\s*::=\s*(SEQUENCE|CHOICE|ENUMERATED)\s*{(.*?)}(?=\s*(?:[A-Za-z-]+\s*::=\s*(?:SEQUENCE|CHOICE|ENUMERATED)|END)\b)', asn, flags=re.DOTALL):
        if type in ('SEQUENCE', 'CHOICE'):
            for definitions in re.sub(r'{[^}]*}', '', definition).split(','):
                definitions = re.sub(r'\bSET OF\b|\(.*\).*', '', definitions).strip().split(maxsplit=1)
                if definitions:
                    mapping.setdefault(name if type == 'SEQUENCE' else (name,), {})[definitions[0]] = definitions[1]
        elif type == 'ENUMERATED':
            mapping[name] = re.findall(r'[A-Za-z-]+', definition)
    return build_definitions(mapping, key)

这样(注意,对于多行字符串文字,最好使用三引号):

ee='''
Module-order DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
Order ::= SEQUENCE {
header Order-header
 }
Order-header ::= SEQUENCE {
reference NumericString (SIZE (12)),
date NumericString (SIZE (8)) -- MMDDYYYY --
}END

seq_list=['Order','Order-header']

condition='Order ::= SEQUENCE {
header Order-header
 }'''

rec_fn(ee, 'Order')将返回:

{'header': {'reference': 'NumericString', 'date': 'NumericString'}}