'while' in list comprehension?

J

jsaul

Hi there,

wouldn't it be useful to have a 'while' conditional in addition to
'if' in list comprehensions?

foo = []
for i in bar:
if len(i) == 0:
break
foo.append(i)

would then turn into

foo = [ i for i in bar while len(i)>0 ]

Is there any reason for not having this kind of thing? I actually
miss it pretty often.

Cheers, jsaul
 
E

Emile van Sebille

jsaul asks...
would then turn into

foo = [ i for i in bar while len(i)>0 ]

Is there any reason for not having this kind of thing? I actually
miss it pretty often.


How is this different from:

foo = [ i for i in bar if len(i) ]

Emile van Sebille
(e-mail address removed)
 
S

Skip Montanaro

>> foo = [ i for i in bar while len(i)>0 ]

Emile> How is this different from:

Emile> foo = [ i for i in bar if len(i) ]

The first is like:

_ = []
for i in bar:
if not (len(i) > 0):
break
_.append(i)
return _

The second is like:

_ = []
for i in bar:
if len(i) > 0:
_.append(i)
return _

Skip
 
B

Bob Gailer

At said:
jsaul asks...
would then turn into

foo = [ i for i in bar while len(i)>0 ]

Is there any reason for not having this kind of thing? I actually
miss it pretty often.


How is this different from:

foo = [ i for i in bar if len(i) ]

My reading is that the comprehension would stop at the first i whose len
were 0. e.g.
foo = []
for i in bar:
if len(i) == 0:break
foo.append(i)

Bob Gailer
(e-mail address removed)
303 442 2625
 
J

Jeff Epler

Use 2.3's itertools:
foo = [i for i in itertools.takewhile(lambda i: len(i) > 0, bar)]
or maybe
foo = list(itertools.takewhile(len, bar)]
or even
foo = itertools.takewhile(len, bar) # an iterable, not a list

Jeff
 
F

Francis Avila

Emile van Sebille said:
jsaul asks...
would then turn into

foo = [ i for i in bar while len(i)>0 ]

Is there any reason for not having this kind of thing? I actually
miss it pretty often.


How is this different from:

foo = [ i for i in bar if len(i) ]

Emile van Sebille
(e-mail address removed)

The idea is that 'while' stops iterating through the list when the condition
isn't met. 'if' just doesn't output anything. e.g.:
bar = ['this', 'is', 'a', 'list', '', 'see?']
[i for i in bar if len(i)] ['this', 'is', 'a', 'list', 'see?']
[i for i in bar while len(i)] # Pretend
['this', 'is', 'a', 'list']

What's your typical use for this?

I guess I see nothing really wrong with it, although I thought list
comprehensions were supposed to make the iteration transparent--'while'
kinda destroys the illusion. But these are the only two looping constructs
that make sense in a list comprehension, so why not support both? OTOH,
'while' makes no sense in a dictionary comprehension (and presumably we'll
have those one day.)
 
H

Hung Jung Lu

jsaul said:
foo = [ i for i in bar while len(i)>0 ]

Is there any reason for not having this kind of thing? I actually
miss it pretty often.

Could you provide an example where you need it?

From your message, it seems "bar" might be a list of strings. If so, you could use:

foo = bar[:bar.index('')]

regards,

Hung Jung
 
T

Terry Reedy

jsaul said:
Hi there,

wouldn't it be useful to have a 'while' conditional in addition to
'if' in list comprehensions?

foo = []
for i in bar:
if len(i) == 0:
break
foo.append(i)

would then turn into

foo = [ i for i in bar while len(i)>0 ]

while is simply not same as if: break!
if executes once for each value of i, while indefinitely.
If you translate back by current rule, which will not change, you get:

foo = []
for i in bar:
while len(i) >0:
foo.append(i)

Terry J. Reedy
 
S

Stephen Horne

while is simply not same as if: break!
if executes once for each value of i, while indefinitely.
If you translate back by current rule, which will not change, you get:

'while' is an English word which has meaning independant of the
existing Python 'while' loop. It is not necessarily wrong to apply a
different aspect of that meaning in a list comprehension.

Besides, I read the syntax as equating to...

foo = []
for i in bar while len(i) >0:
foo.append(i)

Yes, I know that isn't a legal Python loop. My point is that it didn't
look like a nested loop to me, but rather like an additional qualifier
on the existing loop.

That said, you do have a point - multiple 'for' parts in a list
comprehension act as nested loops, so maybe a while part should too.

The trouble is that a standalone while loop probably makes little
sense in a list comprehension - sure you have a place to put the loop
condition, but what about the initialisation and body?

If there were a real while-part in a list comprehension, it would
probably need those things to become explicit (becoming a lot like the
C for loop) - something like...

[k while k=1; k<1024; k*=2]

Hmmmm...

while i=0; i<10; i++ :
print i

Hmmmm....

Nah - damn silly idea.
 
J

jsaul

* Terry Reedy [2003-10-23 04:57]:
jsaul said:
wouldn't it be useful to have a 'while' conditional in addition to
'if' in list comprehensions?

foo = []
for i in bar:
if len(i) == 0:
break
foo.append(i)

would then turn into

foo = [ i for i in bar while len(i)>0 ]

while is simply not same as if: break!
if executes once for each value of i, while indefinitely.
If you translate back by current rule, which will not change, you get:

foo = []
for i in bar:
while len(i) >0:
foo.append(i)

I agree that 'while' cannot not just be considered a replacement
for 'if'. However, adding a 'while' conditional to list
comprehensions would very unlikely be misunderstood as another
(infinite) loop. Instead, I find the above 'while' example about
as intuitive as is the case with 'if'. It simply means that under
a certain condition the loop will be ended, which is just what
most people would probably expect.

Anyway, thanks a lot to all who replied! What is your opinion
after this discussion, write a PEP or just forget about it?

Cheers, jsaul
 
M

Michael Geary

wouldn't it be useful to have a 'while' conditional in addition to
'if' in list comprehensions?

foo = []
for i in bar:
if len(i) == 0:
break
foo.append(i)

would then turn into

foo = [ i for i in bar while len(i)>0 ]

while is simply not same as if: break!
if executes once for each value of i, while indefinitely.
If you translate back by current rule, which will not change, you get:

foo = []
for i in bar:
while len(i) >0:
foo.append(i)

I agree that 'while' cannot not just be considered a replacement
for 'if'. However, adding a 'while' conditional to list
comprehensions would very unlikely be misunderstood as another
(infinite) loop. Instead, I find the above 'while' example about
as intuitive as is the case with 'if'. It simply means that under
a certain condition the loop will be ended, which is just what
most people would probably expect.

Here's an idea that might avoid this bit of confusion:

foo = [ i for i in bar until len(i) == 0 ]

That also makes the conditional test the same as used in the "if/break"
form.

Hmm... Would this mean that "until" would have to become a reserved word?
Maybe not such a good idea if that's the case.

-Mike
 
A

Andrae Muys

Jeff Epler said:
Use 2.3's itertools:
foo = [i for i in itertools.takewhile(lambda i: len(i) > 0, bar)]
or maybe
foo = list(itertools.takewhile(len, bar)]
or even
foo = itertools.takewhile(len, bar) # an iterable, not a list

or list(takewhile(len, bar))

from itertools import * :)

Andrae
 
H

Hannu Kankaanp??

Michael Geary said:
Here's an idea that might avoid this bit of confusion:

foo = [ i for i in bar until len(i) == 0 ]

Another variation:

foo = [i for i in bar, break if len(i) == 0]

This wouldn't need a new keyword.
 
G

Greg Ewing (using news.cis.dfn.de)

Hannu said:
Another variation:

foo = [i for i in bar, break if len(i) == 0]

This wouldn't need a new keyword.

My thoughts on all this are that if you want to do
something that procedural, it would be better written
out as nested statements. List comprehensions are
meant to be read declaratively.
 
A

Alex Martelli

Greg said:
Hannu said:
Another variation:

foo = [i for i in bar, break if len(i) == 0]

This wouldn't need a new keyword.

My thoughts on all this are that if you want to do
something that procedural, it would be better written
out as nested statements. List comprehensions are
meant to be read declaratively.

Yes, they are. Still,

[ i for i in bar while len(i) ]

DOES read pretty declaratively to me (while the "break"
version admittedly doesn't).


Alex
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top