Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List Comprehension For Loop + Ternary Operation For Loop?

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?

like image 982
Bee Smears Avatar asked Mar 29 '14 18:03

Bee Smears


2 Answers

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.

like image 75
Martijn Pieters Avatar answered Nov 08 '22 23:11

Martijn Pieters


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()]
like image 3
poke Avatar answered Nov 08 '22 23:11

poke