假设我们需要一个程序,它接受一个字符串列表并将它们拆分,然后将一个元组中的前两个单词追加到一个列表中并返回该列表;换句话说,一个程序,它给你每个字符串的前两个单词。
input: ["hello world how are you", "foo bar baz"]
output: [("hello", "world"), ("foo", "bar")]
可以像这样编写(我们假设有效输入):
def firstTwoWords(strings):
result = []
for s in strings:
splt = s.split()
result.append((splt[0], splt[1]))
return result
但列表理解会更好。
def firstTwoWords(strings):
return [(s.split()[0], s.split()[1]) for s in strings]
但这涉及到split()
的两次调用。 有没有办法在理解中只执行一次拆分?我尝试了自然而然的语法无效:
>>> [(splt[0],splt[1]) for s in strings with s.split() as splt]
File "<stdin>", line 1
[(splt[0],splt[1]) for s in strings with s.split() as splt]
^
SyntaxError: invalid syntax
答案 0 :(得分:6)
嗯,在这个特殊情况下:
def firstTwoWords(strings):
return [s.split()[:2] for s in strings]
否则,您可以使用一个生成器表达式:
def firstTwoWords(strings):
return [(s[0], s[1]) for s in (s.split() for s in strings)]
如果性能实际上很重要,那就使用一个函数。
答案 1 :(得分:4)
不幸的是,写出自然会从英语中浮现的想法并希望它的有效语法很少有用。
您尝试做的事情的一般形式是将一些表达式绑定到理解中的名称。没有直接支持,但由于理解中的for
子句依次将名称绑定到序列中的每个元素,因此可以使用for
而不是单个元素容器来实现相同的效果:
>>> strings = ["hello world how are you", "foo bar baz"]
>>> [(splt[0],splt[1]) for s in strings for splt in [s.split()]]
[('hello', 'world'), ('foo', 'bar')]
答案 2 :(得分:2)
我认为使用genexp更好,但是如何使用lambda
进行操作。可能存在更合适的情况
>>> [(lambda splt:(splt[0], splt[1]))(s.split()) for s in input]
[('hello', 'world'), ('foo', 'bar')]
答案 3 :(得分:2)
minitech的答案是正确的方法。
但请注意,您不必在一行中完成所有操作,而且您实际上并没有获得任何收益。
此:
splits = (s.split() for s in strings)
return [(s[0], s[1]) for s in splits]
与此完全相同:
return [(s[0], s[1]) for s in (s.split() for s in strings)]
没有构建额外的中间值,对垃圾收集没有影响,只是免费提供更多可读性。
此外,您的真实代码很可能实际上不需要最终列表,只是可迭代的东西,在这种情况下,您最好用这个:
splits = (s.split() for s in strings)
return ((s[0], s[1]) for s in splits)
或者,在Python 3.3 +中:
splits = (s.split() for s in strings)
yield from ((s[0], s[1]) for s in splits)
事实上,很多程序都可以用这种方式编写 - 一系列生成器表达式,后跟return
/ {{}}最后一个genexpr / listcomp。
答案 4 :(得分:1)
喜欢这个吗?
def firstTwoWords(strings):
return [s.split()[:2] for s in strings]
它使用列表拼接。它将返回一个列表,但如果你想要一个元组,你可以使用:
def firstTwoWords(strings):
return [tuple(s.split()[:2]) for s in strings]
答案 5 :(得分:0)
itemgetter
可以在这里使用。它比s.split()[:2]
更普遍。它允许您从s
>>> from operator import itemgetter
>>> strings = ["hello world how are you", "foo bar baz"]
>>> [itemgetter(0, 1)(s.split()) for s in strings]
[('hello', 'world'), ('foo', 'bar')]
更一般地说:
>>> [itemgetter(1, 2, 0)(s.split()) for s in strings]
[('world', 'how', 'hello'), ('bar', 'baz', 'foo')]