I think I understand list comprehensions and ternary operation, and I understand that I can combine the two, as seen here. My question involves combining the two expressions within one list comprehension.
For instance, if I have the following list:
lst = ['word','word','multiple words','word']
and I want to modify that list in one line, is there a way of doing so? I tried what I thought was the most obvious construction:
lst[:] = [word for word in word.split() if ' ' in word else word for word in lst]
That throws a syntax error. Is there a way of doing this in one line?
You don't need any conditional expression* here, as str.split()
always returns a list, even if only containing one word:
lst[:] = [word for words in lst for word in words.split()]
Demo:
>>> lst = ['word','word','multiple words','word']
>>> [word for words in lst for word in words.split()]
['word', 'word', 'multiple', 'words', 'word']
The conditional expression can be used wherever you could use a simple expression in the syntax; that means anywhere it says expression
or old_expression
in the list display grammar:
list_display ::= "[" [expression_list | list_comprehension] "]"
list_comprehension ::= expression list_for
list_for ::= "for" target_list "in" old_expression_list [list_iter]
old_expression_list ::= old_expression [("," old_expression)+ [","]]
old_expression ::= or_test | old_lambda_expr
list_iter ::= list_for | list_if
list_if ::= "if" old_expression [list_iter]
So the first part of a list comprehension, but also the part that produces the outermost iterator (evaluated once), the if
expressions, or any of the nested iterators (evaluated each iteration of the next outer for
loop).
*It's called the conditional expression; it is a ternary operator, but so is the SQL BETWEEN
operator.
First of all, you have the order wrong. To use the ternary operator, you have to do it like this:
[a if c else b for item in list]
That being said, you cannot really have another list comprehension level embedded depending on some condition. The number of levels has to be fixed.
As you are just looking to split for whitespace, you can just perform this anyway though, as splitting a string without whitespace will still give you back a list with a single item back:
[subword for word in list for subword in word.split()]