else condition in list comprehension

Discussion in 'Python' started by Luis M. Gonzalez, Jan 9, 2005.

  1. 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?
    Luis M. Gonzalez, Jan 9, 2005
    #1
    1. Advertising

  2. Luis M. Gonzalez wrote:
    > 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
    Reinhold Birkenfeld, Jan 9, 2005
    #2
    1. Advertising

  3. Luis M. Gonzalez wrote:
    > 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.

    --
    Ciao,
    Matteo
    Matteo Dell'Amico, Jan 9, 2005
    #3
  4. Thank you guys!
    Luis M. Gonzalez, Jan 9, 2005
    #4
  5. Matteo Dell'Amico wrote:
    > Luis M. Gonzalez wrote:
    >> 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
    Reinhold Birkenfeld, Jan 9, 2005
    #5
  6. Luis M. Gonzalez

    Dan Bishop Guest

    Luis M. Gonzalez wrote:
    > 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.)
    Dan Bishop, Jan 9, 2005
    #6
  7. Luis M. Gonzalez

    It's me Guest

    > 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"?
    It's me, Jan 10, 2005
    #7
  8. It's me wrote:
    > > 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.
    Luis M. Gonzalez, Jan 10, 2005
    #8
  9. Luis M. Gonzalez wrote:
    > It's me wrote:
    >>> 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
    Steven Bethard, Jan 10, 2005
    #9
  10. Luis M. Gonzalez

    Nick Coghlan Guest

    Dan Bishop wrote:
    > Luis M. Gonzalez wrote:
    >
    >>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.

    --
    Nick Coghlan | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
    Nick Coghlan, Jan 11, 2005
    #10
  11. Luis M. Gonzalez

    Anthony Guest

    On Mon, 10 Jan 2005 09:13:17 -0700, Steven Bethard
    <> wrote:
    > Luis M. Gonzalez wrote:
    > > It's me wrote:
    > >>> 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

    --
    -----------------------------------------------------
    HyPEraCtiVE? HeY, WhO aRE YoU cALliNg HypERaCtIve?!

    -----------------------------------------------------
    Anthony, Jan 11, 2005
    #11
  12. Nick Coghlan wrote:

    > Dan Bishop wrote:
    >
    >> Luis M. Gonzalez wrote:
    >>
    >>> 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)]

    --
    Serhiy Storchaka
    Serhiy Storchaka1659322541, Jan 11, 2005
    #12
  13. Luis M. Gonzalez

    Nick Coghlan Guest

    Luis M. Gonzalez wrote:
    > 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.

    --
    Nick Coghlan | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
    Nick Coghlan, Jan 12, 2005
    #13
  14. Luis M. Gonzalez

    Steve Holden Guest

    Nick Coghlan wrote:

    > Luis M. Gonzalez wrote:
    >
    >> 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
    --
    Steve Holden http://www.holdenweb.com/
    Python Web Programming http://pydish.holdenweb.com/
    Holden Web LLC +1 703 861 4237 +1 800 494 3119
    Steve Holden, Jan 12, 2005
    #14
  15. On 9 Jan 2005 12:20:40 -0800, Luis M. Gonzalez <> wrote:
    > 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.
    Stephen Thorne, Jan 12, 2005
    #15
  16. Steve Holden wrote:
    > Nick Coghlan wrote:
    >> 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
    Steven Bethard, Jan 13, 2005
    #16
  17. Steve Holden wrote:
    > Nick Coghlan wrote:
    >
    >> Luis M. Gonzalez wrote:
    >>
    >>> 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.
    Andrey Tatarinov, Jan 13, 2005
    #17
  18. Luis M. Gonzalez

    Nick Coghlan Guest

    Andrey Tatarinov wrote:
    >> 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.


    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.

    --
    Nick Coghlan | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
    Nick Coghlan, Jan 13, 2005
    #18
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. -
    Replies:
    12
    Views:
    688
    Remon van Vliet
    Jun 15, 2005
  2. Debajit Adhikary
    Replies:
    17
    Views:
    681
    Debajit Adhikary
    Oct 18, 2007
  3. Vedran Furac(
    Replies:
    4
    Views:
    323
    Marc 'BlackJack' Rintsch
    Dec 19, 2008
  4. Mike H
    Replies:
    13
    Views:
    556
    Diez B. Roggisch
    Apr 12, 2009
  5. Bill W.
    Replies:
    13
    Views:
    290
    Phillip Gawlowski
    May 9, 2011
Loading...

Share This Page