【问题标题】:Return list of words from a list of lines with regexp使用正则表达式从行列表中返回单词列表
【发布时间】:2010-04-06 16:05:05
【问题描述】:

我在字符串列表上运行以下代码以返回其单词列表:

words = [re.split('\\s+', line) for line in lines]

但是,我最终得到了类似的东西:

[['import', 're', ''], ['', ''], ['def', 'word_count(filename):', ''], ...]

与期望相反:

['import', 're', '', '', '', 'def', 'word_count(filename):', '', ...]

如何解压缩上述列表理解中re.split('\\s+', line) 生成的列表?天真地,我尝试使用 * 但这不起作用。

(我正在寻找一种简单的 Pythonic 方式;我很想编写一个函数,但我确信该语言可以解决这个问题。)

【问题讨论】:

  • 当我想念 Haskell 的 concatMap 时,就是这样的时候......

标签: python regex python-3.x list-comprehension


【解决方案1】:
>>> import re
>>> from itertools import chain
>>> lines = ["hello world", "second line", "third line"]
>>> words = chain(*[re.split(r'\s+', line) for line in lines])

这将为您提供一个可用于遍历所有单词的迭代器:

>>> for word in words:
...    print(word)
... 
hello
world
second
line
third
line

创建列表而不是迭代器只需将迭代器包装在 list 调用中:

>>> words = list(chain(*[re.split(r'\s+', line) for line in lines]))

【讨论】:

  • 非常棒的方法,虽然我很失望 Python 不允许使用不那么“混乱”的方法。干杯。
  • 或者,您可以使用chain.from_iterable 而无需解压列表。
  • 更容易反向嵌套理解
【解决方案2】:

您获得列表列表的原因是因为 re.split() 返回一个列表,然后该列表“附加”到列表理解输出中。

尚不清楚您为什么要使用它(或者可能只是一个不好的例子),但是如果您可以将完整内容(所有行)作为字符串获取,则可以这样做

words = re.split(r'\s+', lines)

如果行是以下的乘积:

open('filename').readlines()

使用

open('filename').read()

改为。

【讨论】:

  • 使用 Python 3 的人!没有更多的 readlines(),一切都是 Unicode。
  • 另外,re.split 不接受列表参数(我已经尝试过了)。
  • @Kevin True;但是,我使用的是list(file)
  • @Beau,看着你的例子,除了来自文件或类似文件的类型之外,我想不出其他任何东西。因此,将其作为字符串读取(如上所述)是可行的。
【解决方案3】:

你总是可以这样做:

words = []
for line in lines:
  words.extend(re.split('\\s+',line))

它不像单行列表理解那样优雅,但它可以完成工作。

【讨论】:

    【解决方案4】:

    刚刚偶然发现这个老问题,我想我有一个更好的解决方案。通常,如果你想嵌套一个列表推导(“附加”每个列表),你会向后思考(类似 un-for-loop)。这不是你想要的:

    >>> import re
    >>> lines = ["hello world", "second line", "third line"]
    >>> [[word for word in re.split(r'\s+', line)] for line in lines]
    [['hello', 'world'], ['second', 'line'], ['third', 'line']]
    

    但是,如果您想“扩展”而不是“附加”正在生成的列表,只需省略额外的方括号集并反转您的 for 循环(将它们放回“正确”顺序)。

    >>> [word for line in lines for word in re.split(r'\s+', line)]
    ['hello', 'world', 'second', 'line', 'third', 'line']
    

    这对我来说似乎是一个更 Pythonic 的解决方案,因为它基于列表处理逻辑,而不是一些随机的内置函数。每个程序员都应该知道如何做到这一点(尤其是那些试图学习 Lisp 的人!)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-10
      • 2020-08-03
      • 1970-01-01
      • 2013-02-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多