我在字符串列表上运行以下代码以返回其单词列表:
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方式;我很想写一个函数,但我确信该语言可以适应这个问题。)
答案 0 :(得分:4)
>>> 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]))
答案 1 :(得分:1)
你得到列表列表的原因是因为re.split()返回一个列表,然后“追加”到列表推导输出中。
目前还不清楚为什么要使用它(或者可能只是一个不好的例子),但是如果你可以将完整内容(所有行)作为一个字符串,你可以做到
words = re.split(r'\s+', lines)
如果行是以下产品:
open('filename').readlines()
使用
open('filename').read()
代替。
答案 2 :(得分:0)
您可以随时执行此操作:
words = []
for line in lines:
words.extend(re.split('\\s+',line))
它不像单线列表理解那样优雅,但它完成了工作。
答案 3 :(得分:0)
偶然发现了这个老问题,我想我有更好的解决方案。通常,如果你想嵌套一个列表理解(“追加”每个列表),你会倒退(不像循环一样)。这不是你想要的:
>>> 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的人!)