Say we need a program which takes a list of strings and splits them, and appends the first two words, in a tuple, to a list and returns that list; in other words, a program which gives you the first two words of each string.
input: ["hello world how are you", "foo bar baz"]
output: [("hello", "world"), ("foo", "bar")]
It can be written like so (we assume valid input):
def firstTwoWords(strings):
result = []
for s in strings:
splt = s.split()
result.append((splt[0], splt[1]))
return result
But a list comprehension would be much nicer.
def firstTwoWords(strings):
return [(s.split()[0], s.split()[1]) for s in strings]
But this involves two calls to split()
. Is there a way to perform the split only once from within the comprehension? I tried what came naturally and it was invalid syntax:
>>> [(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
Well, in this particular case:
def firstTwoWords(strings):
return [s.split()[:2] for s in strings]
Otherwise, though, you can use one generator expression:
def firstTwoWords(strings):
return [(s[0], s[1]) for s in (s.split() for s in strings)]
And if performance is actually critical, just use a function.
Writing what comes to mind naturally from English and hoping it's valid syntax rarely works, unfortunately.
The generalized form of what you're trying to do is bind some expression to a name within a comprehension. There's no direct support to that, but since a for
clause in a comprehension binds a name to each element from a sequence in turn, you can use for
over single-element containers to achieve the same effect:
>>> 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')]
I think using a genexp is nicer, but here's how to do it with a lambda
. There may be cases when this is a better fit
>>> [(lambda splt:(splt[0], splt[1]))(s.split()) for s in input]
[('hello', 'world'), ('foo', 'bar')]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With