【问题标题】:string processing while parsing into dictionary解析成字典时的字符串处理
【发布时间】:2013-05-15 15:12:43
【问题描述】:

我有一个格式如下的字符串:

"2A:xxx\r\n3A:yyyy\r\n51:yzzzz\r\n52:yzyeys\r\n4A:....."

这需要通过在\r\n处拆分来转换成字典。
然而,困难的部分是,对于 3A 和 4A 之间的对,密钥需要预先添加 3A,以表明它们是 3A 的子集。
所以最终的预期输出如下:

{'2A':'xxxx','3A':'yyyy','3A-51':'yzzzz','3A-52':'yzyeys','4A':'.....}

有没有比将所有数据提取到字典中并稍后使用 for 循环遍历字典更简单的方法。 这可以在单个解析进程中完成吗?

【问题讨论】:

    标签: python


    【解决方案1】:

    str.splitlines() 为您完成大部分工作:

    >>> "2A:xxx\r\n3A:yyyy\r\n51:yzzzz\r\n52:yzyeys\r\n4A:.....".splitlines()
    ['2A:xxx', '3A:yyyy', '51:yzzzz', '52:yzyeys', '4A:.....']
    

    这里的棘手之处在于跟踪3A 键;大概是定义层次结构的键中的A

    最好将其拆分为生成器:

    def hierarchy_key_values(lines):
        parent = ''
        for line in lines:
            key, value = line.split(':', 1)
            if key[-1] == 'A':
                parent = key + '-'
            else:
                key = parent + key
    
            yield key, value
    

    剩下的很简单:

    your_dict = dict(hierarchy_key_values(input_text.splitlines()))
    

    使用您的示例输入进行演示:

    >>> dict(hierarchy_key_values(input_text.splitlines()))
    {'3A-52': 'yzyeys', '3A': 'yyyy', '3A-51': 'yzzzz', '2A': 'xxx', '4A': '.....'}
    

    【讨论】:

      【解决方案2】:

      在我的头顶:

       dct = {}
       last = ''
       for line in s.splitlines():
          key, val = line.split(':')
          if key.isdigit():
              key = last + '-' + key
           else:
              last = key
           dct[key] = val
      

      这可行,但使用“复合”键通常不是使用分层结构的最佳方式。我会建议这样的东西:

      dct = {}
      last = ''
      for line in s.splitlines():
          key, val = line.split(':')
          if key.isdigit():
              dct[last].setdefault('items', {})[key] = {'value': val }
          else:
              dct[key] = {'value': val }
              last = key
      

      这使得字典像:

      {'2A': {'value': 'xxx'},
       '3A': {'items': {'51': {'value': 'yzzzz'}, '52': {'value': 'yzyeys'}},
              'value': 'yyyy'},
       '4A': {'value': '.....'}}
      

      看起来更复杂,但实际上使用起来会容易得多。

      【讨论】:

        【解决方案3】:
        def solve(strs):
            dic = {}
            prev = None
            for x in strs.splitlines():
                key,val = x.split(":")
                if "A" not in key:                #or key.isdigit()
                    new_key = "-".join((prev,key))
                    dic[new_key] = val
                else:
                    dic[key] = val
                    prev = key
            return dic
        strs = "2A:xxx\r\n3A:yyyy\r\n51:yzzzz\r\n52:yzyeys\r\n4A:"
        print solve(strs)    
        

        输出:

        {'3A-52': 'yzyeys', '3A': 'yyyy', '3A-51': 'yzzzz', '2A': 'xxx', '4A': ''}
        

        【讨论】:

          【解决方案4】:

          使用reduce 函数,您可以在迭代时保留内存,然后使用单线成功:

          >>> import re
          >>> reduce(lambda col, x: x + [y if re.match(r'\d+A.*', y) else col[-1][0:2] + '-' + y], s.split('\r\n'), [])
          ['2A:xxx', '3A:yyyy', '3A-51:yzzzz', '3A-52:yzyeys', '4A:.....']
          

          正如 Martin 所说,split 函数将字符串拆分为多个部分,reduce 收集正在填充的集合和新元素。因此,您可以查看添加的最后一个元素 (x[-1]) 以获取其标识符。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-02-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-27
            • 2015-06-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多