【问题标题】:Recursive function for nested dictionaries嵌套字典的递归函数
【发布时间】:2018-09-21 07:01:56
【问题描述】:

我有一个 asn 格式的文本文件,现在我正在编写我自己的解析器,在这个例子中,它最初为 Order 创建一个字典,然后进入项目内部,看看值是否不是字典,字典在文件中已被识别并保存在 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

【问题讨论】:

  • 根据您的示例输入,rec_fn() 的预期输出是多少?
  • {header:{reference:Numericstring,date:numericstring}}
  • 但是order 去哪儿了?
  • order 是最初识别的字典,我只关心它的内容,它就像 order={header:{reference:Numericstring,date:numericstring}}

标签: python dictionary recursion


【解决方案1】:

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

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'}}

【讨论】:

    猜你喜欢
    • 2021-12-04
    • 1970-01-01
    • 2016-02-05
    • 2021-11-01
    • 2017-02-16
    • 1970-01-01
    • 2013-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多