else condition in list comprehension

  • Thread starter Luis M. Gonzalez
  • Start date
L

Luis M. Gonzalez

Hi there,

I'd like to know if there is a way to add and else condition into a
list comprehension. I'm sure that I read somewhere an easy way to do
it, but I forgot it and now I can't find it...

for example:
z=[i+2 for i in range(10) if i%2==0]
what if I want i to be "i-2" if i%2 is not equal to 0?
 
R

Reinhold Birkenfeld

Luis said:
Hi there,

I'd like to know if there is a way to add and else condition into a
list comprehension. I'm sure that I read somewhere an easy way to do
it, but I forgot it and now I can't find it...

for example:
z=[i+2 for i in range(10) if i%2==0]
what if I want i to be "i-2" if i%2 is not equal to 0?

You'll have to add the condition at the front:

z = [(i+2, i-2)[i%2] for i in range(10)]

should do what you need.

Reinhold
 
M

Matteo Dell'Amico

Luis said:
Hi there,

I'd like to know if there is a way to add and else condition into a
list comprehension. I'm sure that I read somewhere an easy way to do
it, but I forgot it and now I can't find it...

for example:
z=[i+2 for i in range(10) if i%2==0]
what if I want i to be "i-2" if i%2 is not equal to 0?

You could use

[(i-2, i+2)[bool(i%2 == 0)] for i in range(10)]

or, in a less general but shorter way

[(i+2, i-2)[i%2] for i in range(10)]

or even

[i%2 and i-2 or i+2 for i in range(10)]

The "if" clause in comprehensions is used as a filter condition.
 
R

Reinhold Birkenfeld

Matteo said:
Luis said:
Hi there,

I'd like to know if there is a way to add and else condition into a
list comprehension. I'm sure that I read somewhere an easy way to do
it, but I forgot it and now I can't find it...

for example:
z=[i+2 for i in range(10) if i%2==0]
what if I want i to be "i-2" if i%2 is not equal to 0?

You could use

[(i-2, i+2)[bool(i%2 == 0)] for i in range(10)]

or, in a less general but shorter way

[(i+2, i-2)[i%2] for i in range(10)]

or even

[i%2 and i-2 or i+2 for i in range(10)]

One should note that the (cond and X or Y) construct only works if X can
never produce a false value (such as 0, "", []). In this example, it is
okay, but replace 2 with 1 and you will run into trouble for i = 1.

Reinhold
 
D

Dan Bishop

Luis said:
Hi there,

I'd like to know if there is a way to add and else condition into a
list comprehension. I'm sure that I read somewhere an easy way to do
it, but I forgot it and now I can't find it...

for example:
z=[i+2 for i in range(10) if i%2==0]
what if I want i [sic] to be "i-2" if i%2 is not equal to 0?

z = [i + (2, -2)[i % 2] for i in range(10)]

In general, the expression "T if C is true, or F if C is false" can be
written as (F, T)[bool(C)]. (If you know that C will always be either
0 or 1, as is the case here, the "bool" is redundant.)

Unless, of course, either F or T has side effects. For a side-effect
free expression, you can use (C and [T] or [F])[0] or one of the many
other ternary operator substitutes. (Search for PEP 308.)
 
I

It's me

z = [i + (2, -2)[i % 2] for i in range(10)]

But then why would you want to use such feature? Wouldn't that make the
code much harder to understand then simply:

z=[]
for i in range(10):
if i%2:
z.append(i-2)
else:
z.append(i+2)

Or are we trying to write a book on "Puzzles in Python"?
 
L

Luis M. Gonzalez

It's me said:
z = [i + (2, -2)[i % 2] for i in range(10)]

But then why would you want to use such feature? Wouldn't that make the
code much harder to understand then simply:

z=[]
for i in range(10):
if i%2:
z.append(i-2)
else:
z.append(i+2)

Or are we trying to write a book on "Puzzles in Python"?


Once you get used to list comprehensions (and it doesn't take long),
they are a more concise and compact way to express these operations.
I think that writing 6 lines instead of 1 could be more readable of you
are a beginner, but after playing a little bit with listcomps for the
first time, you'll see they are very practical yet readable.
 
S

Steven Bethard

Luis said:
It's me said:
z = [i + (2, -2)[i % 2] for i in range(10)]

But then why would you want to use such feature? Wouldn't that make
the code much harder to understand then simply:

z=[]
for i in range(10):
if i%2:
z.append(i-2)
else:
z.append(i+2)

Or are we trying to write a book on "Puzzles in Python"?

Once you get used to list comprehensions (and it doesn't take long),
they are a more concise and compact way to express these operations.

After looking the two suggestions over a couple of times, I'm still
undecided as to which one is more readable for me. The problem is not
the list comprehensions (which I love and use extensively). The problem
is the odd syntax that has to be used for an if/then/else expression in
Python. I think I would have less trouble reading something like:

z = [i + (if i % 2 then -2 else 2) for i in range(10)]

but, of course, adding a if/then/else expression to Python is unlikely
to ever happen -- see the rejected PEP 308[1].

Steve

[1] http://www.python.org/peps/pep-0308.html
 
N

Nick Coghlan

Dan said:
Luis said:
Hi there,

I'd like to know if there is a way to add and else condition into a
list comprehension. I'm sure that I read somewhere an easy way to do
it, but I forgot it and now I can't find it...

for example:
z=[i+2 for i in range(10) if i%2==0]
what if I want i [sic] to be "i-2" if i%2 is not equal to 0?


z = [i + (2, -2)[i % 2] for i in range(10)]

For the specific case of +/- a number, (-1) ** x works, too:

z = [i + 2 * ((-1) ** i) for i in range(10)]

Not that I'm claiming it's particularly readable or anything. . . just that it
works :)

Cheers,
Nick.
 
A

Anthony

Luis said:
It's me said:
z = [i + (2, -2)[i % 2] for i in range(10)]

But then why would you want to use such feature? Wouldn't that make
the code much harder to understand ...
Or are we trying to write a book on "Puzzles in Python"?

Once you get used to list comprehensions (and it doesn't take long),
they are a more concise and compact way to express these operations.

After looking the two suggestions over a couple of times, I'm still
undecided as to which one is more readable for me. The problem is not
the list comprehensions (which I love and use extensively). The problem
is the odd syntax that has to be used for an if/then/else expression in
Python.

They're both pretty unreadable, IMHO. Why not just factor out the
if/then/else function like this:

..def plusMinusTwo(i):
.. if i%2 == 0:
.. return i-2
.. else:
.. return i+2
..
..z = [plusMinusTwo(i) for i in range(10)]

Then you can add whatever you like into the function.

Anthony
 
S

Serhiy Storchaka1659322541

Nick said:
Dan said:
Luis said:
Hi there,

I'd like to know if there is a way to add and else condition into a
list comprehension. I'm sure that I read somewhere an easy way to do
it, but I forgot it and now I can't find it...

for example:
z=[i+2 for i in range(10) if i%2==0]
what if I want i [sic] to be "i-2" if i%2 is not equal to 0?



z = [i + (2, -2)[i % 2] for i in range(10)]


For the specific case of +/- a number, (-1) ** x works, too:

z = [i + 2 * ((-1) ** i) for i in range(10)]

Not that I'm claiming it's particularly readable or anything. . . just
that it works :)

Yet another variant:
z = [i + ( (i % 2) and -2 or 2 ) for i in range(10)]
 
N

Nick Coghlan

Luis said:
Hi there,

I'd like to know if there is a way to add and else condition into a
list comprehension. I'm sure that I read somewhere an easy way to do
it, but I forgot it and now I can't find it...

for example:
z=[i+2 for i in range(10) if i%2==0]
what if I want i to be "i-2" if i%2 is not equal to 0?

Hmm:

z = [newval(i) for i in range(10)] using:
def newval(x):
if x % 2:
return x - 2
else:
return x + 2

Just some more mental twiddling relating to the thread on statement local
namespaces.

Cheers,
Nick.
 
S

Steve Holden

Nick said:
Luis said:
Hi there,

I'd like to know if there is a way to add and else condition into a
list comprehension. I'm sure that I read somewhere an easy way to do
it, but I forgot it and now I can't find it...

for example:
z=[i+2 for i in range(10) if i%2==0]
what if I want i to be "i-2" if i%2 is not equal to 0?

Hmm:

z = [newval(i) for i in range(10)] using:
def newval(x):
if x % 2:
return x - 2
else:
return x + 2

Just some more mental twiddling relating to the thread on statement
local namespaces.
I presume the point of this is to avoid polluting the local namespace
with "newval". I further presume you also have plans to do something
about "i"? ;-)

regards
Steve
 
S

Stephen Thorne

Hi there,

I'd like to know if there is a way to add and else condition into a
list comprehension. I'm sure that I read somewhere an easy way to do
it, but I forgot it and now I can't find it...

for example:
z=[i+2 for i in range(10) if i%2==0]
what if I want i to be "i-2" if i%2 is not equal to 0?

z = [i+2-(i%2)*4 for i in range(10)]

C'mon, who needs an 'if' statement when we have maths!

Stephen.
 
S

Steven Bethard

Steve said:
Nick said:
z = [newval(i) for i in range(10)] using:
def newval(x):
if x % 2:
return x - 2
else:
return x + 2

Just some more mental twiddling relating to the thread on statement
local namespaces.
I presume the point of this is to avoid polluting the local namespace
with "newval". I further presume you also have plans to do something
about "i"? ;-)

Well, while I'm not at all a fan of the "using" syntax, getting rid of
'i' is simple:

z = list(newval(i) for i in range(10))

=)

Steve
 
A

Andrey Tatarinov

Steve said:
Nick said:
Luis said:
Hi there,

I'd like to know if there is a way to add and else condition into a
list comprehension. I'm sure that I read somewhere an easy way to do
it, but I forgot it and now I can't find it...

for example:
z=[i+2 for i in range(10) if i%2==0]
what if I want i to be "i-2" if i%2 is not equal to 0?

Hmm:

z = [newval(i) for i in range(10)] using:
def newval(x):
if x % 2:
return x - 2
else:
return x + 2

Just some more mental twiddling relating to the thread on statement
local namespaces.
I presume the point of this is to avoid polluting the local namespace
with "newval". I further presume you also have plans to do something
about "i"? ;-)

no, the point is in grouping definition of newval() with place where it
is used.
 
N

Nick Coghlan

Andrey said:
no, the point is in grouping definition of newval() with place where it
is used.

I'd have said the point was both :)

But yeah, unfortunately the 'leaking list comp' problem won't be fixed in the
2.x series due to the compatibility problem. Fortunately, generator expressions
didn't inherit the issue.

Cheers,
Nick.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top