【问题标题】:Build a dictionary from successful regex matches in python从 python 中成功的正则表达式匹配构建字典
【发布时间】:2012-06-21 03:58:21
【问题描述】:

我对 Python 还是很陌生,我正在尝试解析一个文件。文件中只有某些行包含感兴趣的数据,我想最终得到一个从文件中有效匹配行解析的内容的字典。

下面的代码可以工作,但它有点难看,我正在尝试学习它应该如何完成,也许是理解,或者使用多行正则表达式。我正在使用 Python 3.2。

file_data = open('x:\\path\\to\\file','r').readlines()
my_list = []
for line in file_data:
    # discard lines which don't match at all
    if re.search(pattern, line):
        # icky, repeating search!!
        one_tuple = re.search(pattern, line).group(3,2)
        my_list.append(one_tuple)
my_dict = dict(my_list)

您能提出一个更好的实施方案吗?

【问题讨论】:

  • 理解可能很漂亮,但您不能轻易地将变量绑定到其中的值,因此您需要双精度 re.search。只需使用一个循环。

标签: python regex iterable dictionary-comprehension


【解决方案1】:

以下是对代码的一些快速优化:

my_dict = dict()

with open(r'x:\path\to\file', 'r') as data:
    for line in data:
        match = re.search(pattern, line)
        if match:
            one_tuple = match.group(3, 2)
            my_dict[one_tuple[0]] = one_tuple[1]

【讨论】:

    【解决方案2】:

    我不确定我是否会推荐它,但您可以尝试使用推导式来代替(为简单起见,我用字符串代替了文件)

    >>> import re
    >>> data = """1foo bar
    ... 2bing baz
    ... 3spam eggs
    ... nomatch
    ... """
    >>> pattern = r"(.)(\w+)\s(\w+)"
    >>> {x[0]: x[1] for x in (m.group(3, 2) for m in (re.search(pattern, line) for line in data.splitlines()) if m)}
    {'baz': 'bing', 'eggs': 'spam', 'bar': 'foo'}
    

    【讨论】:

    • 字典理解;我喜欢!
    【解决方案3】:

    本着EAFP 的精神,我建议

    with open(r'x:\path\to\file', 'r') as data:
        for line in data:
            try:
                m = re.search(pattern, line)
                my_dict[m.group(2)] = m.group(3)
            except AttributeError:
                pass
    

    另一种方法是继续使用列表,但重新设计模式,使其仅包含两个组(key, value)。然后你可以简单地这样做:

      matches = [re.findall(pattern, line) for line in data]
      mydict = dict(x[0] for x in matches if x)
    

    【讨论】:

      【解决方案4】:

      感谢您的回复。把它们放在一起后,我得到了

      file_data = open('x:\\path\\to\\file','r').read()
      my_list = re.findall(pattern, file_data, re.MULTILINE)
      my_dict = {c:b for a,b,c in my_list}
      

      但我认为如果没有帮助,我今天不可能到达那里。

      【讨论】:

      • 您可能希望将正则表达式中的第一组设为非捕获 (?:) 以跳过理解步骤:my_dict = dict(re.findall...)
      • 相当不错的改进。但是:将所有数据读入一个变量,而不是遍历一个文件对象(并隐式调用readline() 方法),可扩展性不是很好。 re.findall() 在迭代器而不是变量上工作得很好。
      【解决方案5】:
      matchRes = pattern.match(line)
      if matchRes:
          my_dict = matchRes.groupdict()
      

      【讨论】:

      • 请按照您的代码 sn-p 进行一些详细说明,以便读者更清楚地解释。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-07
      • 2016-11-22
      • 2016-06-01
      • 2017-02-19
      • 1970-01-01
      • 2020-08-30
      • 2016-07-01
      相关资源
      最近更新 更多