nested list comprehension and if clauses

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jyotirmoy Bhattacharya

    nested list comprehension and if clauses

    I'm a newcomer to Python. I have just discovered nested list
    comprehensions and I need help to understand how the if-clause
    interacts with the multiple for-clauses. I have this small program:

    def multab(n):
    print 'multab',n
    return [n*i for i in range(5)]

    print [(m,n) for m in range(5) for n in multab(m) if m>2]

    It produces the output:
    multab 0
    multab 1
    multab 2
    multab 3
    multab 4
    [(3, 0), (3, 3), (3, 6), (3, 9), (3, 12), (4, 0), (4, 4), (4, 8), (4,
    12), (4, 16)]

    I was wondering if there is some way to write the if-clause so that it
    is 'hoisted' out of the inner loop and the multab function is not
    called at all for m=0,1,2. That would seem to be important if multab
    were an expensive function.

  • Paul Rubin

    #2
    Re: nested list comprehension and if clauses

    Jyotirmoy Bhattacharya <jmoy.matecon@g mail.comwrites:
    print [(m,n) for m in range(5) for n in multab(m) if m>2]
    I was wondering if there is some way to write the if-clause so that it
    is 'hoisted' out of the inner loop and the multab function is not
    called at all for m=0,1,2. That would seem to be important if multab
    were an expensive function.
    Maybe you mean

    print [(m,n) for m in [a for a in range(5) if a 2] for n in multab(m)]

    You'd probably really write

    print [[(m,n) for m in range(3,5)] for n in multab(m)]

    You should also use xrange instead of range, if the range might be
    large. And you could use a generator expression instead of a listcomp
    for the inner list.

    Comment

    • Alex Martelli

      #3
      Re: nested list comprehension and if clauses

      Jyotirmoy Bhattacharya <jmoy.matecon@g mail.comwrote:
      I'm a newcomer to Python. I have just discovered nested list
      comprehensions and I need help to understand how the if-clause
      interacts with the multiple for-clauses. I have this small program:
      >
      def multab(n):
      print 'multab',n
      return [n*i for i in range(5)]
      >
      print [(m,n) for m in range(5) for n in multab(m) if m>2]
      >
      It produces the output:
      multab 0
      multab 1
      multab 2
      multab 3
      multab 4
      [(3, 0), (3, 3), (3, 6), (3, 9), (3, 12), (4, 0), (4, 4), (4, 8), (4,
      12), (4, 16)]
      >
      I was wondering if there is some way to write the if-clause so that it
      is 'hoisted' out of the inner loop and the multab function is not
      called at all for m=0,1,2. That would seem to be important if multab
      were an expensive function.
      Sure, just place the if clause where it needs to apply (between the two
      for clauses) [apart from the fact that this example is best expressed by
      using range(3,5), as somebody already said;-)].

      Generally, the semantics of:

      x = [<exprfor <F1if <I2for <F3>]

      are exactly those of

      x = []
      for <F1:
      if <I2:
      for<F3:
      x.append(expr)

      and similarly for other mixes of for and if clauses (except that the
      first clause must always be a for clause) -- you can always, simply and
      mechanically conceptually translate them into an equivalent nest of for
      and if statements, ending in a somelist.append (...) [where somelist may
      be a "temporary anonymous" list if you're just going to use the listcomp
      further rather than just assigning it to a name].


      Alex

      Comment

      • Paul Rubin

        #4
        Re: nested list comprehension and if clauses

        aleax@mac.com (Alex Martelli) writes:
        print [(m,n) for m in range(5) for n in multab(m) if m>2]
        Sure, just place the if clause where it needs to apply (between the two
        for clauses) [apart from the fact that this example is best expressed by
        using range(3,5), as somebody already said;-)].
        You mean

        print [(m,n) for m in range(5) if m 2 for n in multab(m)]

        Heh. I didn't realize you could do that. Thanks.

        Comment

        • Alex Martelli

          #5
          Re: nested list comprehension and if clauses

          Paul Rubin <http://phr.cx@NOSPAM.i nvalidwrote:
          aleax@mac.com (Alex Martelli) writes:
          print [(m,n) for m in range(5) for n in multab(m) if m>2]
          Sure, just place the if clause where it needs to apply (between the two
          for clauses) [apart from the fact that this example is best expressed by
          using range(3,5), as somebody already said;-)].
          >
          You mean
          >
          print [(m,n) for m in range(5) if m 2 for n in multab(m)]
          >
          Heh. I didn't realize you could do that. Thanks.
          You're welcome (though a range(3,5) would still be better here:-).


          Alex

          Comment

          • Jyotirmoy Bhattacharya

            #6
            Re: nested list comprehension and if clauses

            On Jun 28, 10:53 am, a...@mac.com (Alex Martelli) wrote:
            Jyotirmoy Bhattacharya <jmoy.mate...@g mail.comwrote:
            print [(m,n) for m in range(5) for n in multab(m) if m>2]
            I was wondering if there is some way to write the if-clause so that it
            is 'hoisted' out of the inner loop and the multab function is not
            called at all for m=0,1,2. That would seem to be important if multab
            were an expensive function.
            Generally, the semantics of:
            >
            x = [<exprfor <F1if <I2for <F3>]
            >
            are exactly those of
            >
            x = []
            for <F1:
            if <I2:
            for<F3:
            x.append(expr)
            >
            Thanks. That makes things completely clear to me.

            Comment

            Working...