473,403 Members | 2,354 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,403 software developers and data experts.

question regarding list comprehensions

Pat
I have written chunks of Python code that look this:

new_array = []
for a in array:
if not len( a ):
continue
new_array.append( a )

and...

string = ""
for r in results:
if not r.startswith( '#' ):
string =+ r

It seems that a list comprehension could clean up the code, but I seem
to have a mental block on list comprehensions. I've read up a lot on
this subject in my books and on the Internet and for whatever reason,
I'm having problems with this idiom (if that's the correct expression).

I've made a number of attempts to solve this on my own but I keep
getting errors.

Could someone please tell me how I could convert the above code to
something more elegant but readily understandable?

Finally, if someone could point me to a good tutorial or explain list
compressions I would be forever in your debt.
Oct 20 '08 #1
5 1073
Pat wrote:
I have written chunks of Python code that look this:

new_array = []
for a in array:
if not len( a ):
continue
new_array.append( a )
new_array = [a for a in array if len(a)]
and...

string = ""
for r in results:
if not r.startswith( '#' ):
string =+ r

"".join(r for r in results if not r.startswith("#"))

Diez
Oct 20 '08 #2
On Mon, 20 Oct 2008 10:20:03 -0400, Pat wrote:
Finally, if someone could point me to a good tutorial or explain list
compressions I would be forever in your debt.
Think of a for-loop:

for x in (1, 2, 3):
x

Creates x=1, then x=2, then x=3. It doesn't do anything with the x's, but
just creates them. Let's turn it into a list comp, and collect the x's:
>>[x for x in (1, 2, 3)]
[1, 2, 3]

for x in (1, 2, 3):
2*x+1

Creates x=1, then evaluates 2*x+1 = 3. Then it repeats for x=2, then x=3.
Here it is as a list comp:
>>[2*x+1 for x in (1, 2, 3)]
[3, 5, 7]

for x in (1, 2, 3):
if x != 2:
2*x+1

Here it is as a list comp:
>>[2*x+1 for x in (1, 2, 3) if x != 2]
[3, 7]
You can use any sort of sequence inside a list comp, not just a tuple.
>>[c.upper() for c in "abcd"]
['A', 'B', 'C', 'D']
You can nest list comps:
>>[y+1 for y in [2*x+1 for x in (1, 2, 3)]]
[4, 6, 8]
Advanced: you can use tuple-unpacking:
>>[(y,x) for (x,y) in [(1,2), (3, 4)]]
[(2, 1), (4, 3)]

and also multiple for-loops:
>>[(x,c) for x in (1, 2) for c in "abc"]
[(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c')]

That last one is close to:

for x in (1, 2):
for c in "abc":
(x, c)
--
Steven
Oct 20 '08 #3
Pat a écrit :
I have written chunks of Python code that look this:

new_array = []
for a in array:
if not len( a ):
continue
new_array.append( a )

# à la lisp
new_array = filter(None, array)

# à la haskell
new_array = [a for a in array if a]

NB : all builtin empty builtin sequence type have a false boolen value,
so 'not len(a)' and 'not a' are usually practicaly equivalent.

<ot>
While we're at it : I assume you mean 'list', not 'array'. That's at
least how the builtin type is named...
</ot>

and...

string = ""
for r in results:
if not r.startswith( '#' ):
string =+ r

# à la lisp
string = "".join(filter(lambda s: not s.startwith('#'), results)

# à la haskell
string = "".join(r for r in results if not s.startswith('#'))
It seems that a list comprehension could clean up the code, but I seem
to have a mental block on list comprehensions. I've read up a lot on
this subject in my books and on the Internet and for whatever reason,
I'm having problems with this idiom (if that's the correct expression).

I've made a number of attempts to solve this on my own but I keep
getting errors.

Could someone please tell me how I could convert the above code to
something more elegant but readily understandable?
Basically, a list expression is written as (pseudo BNF):

'['<expressionfor item in <iterable_expression[if
<conditional_expression>] ']'
where
- <expressionis any Python expression
- <iterable_expressionis any Python expression that evals to an iterable
- the 'if <conditional_expression>' part is optional

The resulting list will be obtained by evaluating <expressionfor each
item of <iterable_expressionfor which <conditional_expressionis
verified.

Since the main goal of list expressions is to build, well, lists, one
usually uses an <expressionthat evals to something we possibly want to
be part of the new list !-)
Now for something more practical:

First let's rewrite your first snippet to get rid of the continue statement:

new_list = []
for item in source_list:
if len(item):
new_list.append(item)
And let's rewrite the second one to replace string concatenation with
the more idiomatic (and much more flexible) list / join idiom:

new_list = []
for item in results:
if not item.startswith('#'):
new_list.append(item)

string = "".join(new_list)
You may start to see a kind of pattern here:

0. new_list = []
1. for item in sequence:
2. if condition(item):
3. new_list.append(item)

The equivalent list comprehension is:

new_list = [item for item in sequence if condition(item)]
Since you didn't apply any transformation to 'item' in your for loops,
the <expressionpart is as simple as it can be : we want the item, period.

The <iterable_expressionis here again quite simple : it's your source
sequence. Ditto for the the <conditional_expression>.

IOW, your for-loop pattern is really:

new_list = []
for item in <iterable_expression>:
if <conditional_expression>:
new_list.append(<expression>)
Once you've identified the different parts, translating this for-loop to
a list comprehension is mostly a matter of reording.

Finally, if someone could point me to a good tutorial or explain list
compressions I would be forever in your debt.
http://en.wikipedia.org/wiki/List_comprehension
http://en.wikipedia.org/wiki/Set-builder_notation
HTH
Oct 20 '08 #4
Pat
Steven D'Aprano wrote:
On Mon, 20 Oct 2008 10:20:03 -0400, Pat wrote:
>Finally, if someone could point me to a good tutorial or explain list
compressions I would be forever in your debt.

Think of a for-loop:

for x in (1, 2, 3):
x

Creates x=1, then x=2, then x=3. It doesn't do anything with the x's, but
just creates them. Let's turn it into a list comp, and collect the x's:
>>>[x for x in (1, 2, 3)]
[1, 2, 3]

for x in (1, 2, 3):
2*x+1

Creates x=1, then evaluates 2*x+1 = 3. Then it repeats for x=2, then x=3.
Here it is as a list comp:
>>>[2*x+1 for x in (1, 2, 3)]
[3, 5, 7]

for x in (1, 2, 3):
if x != 2:
2*x+1

Here it is as a list comp:
>>>[2*x+1 for x in (1, 2, 3) if x != 2]
[3, 7]
You can use any sort of sequence inside a list comp, not just a tuple.
>>>[c.upper() for c in "abcd"]
['A', 'B', 'C', 'D']
You can nest list comps:
>>>[y+1 for y in [2*x+1 for x in (1, 2, 3)]]
[4, 6, 8]
Advanced: you can use tuple-unpacking:
>>>[(y,x) for (x,y) in [(1,2), (3, 4)]]
[(2, 1), (4, 3)]

and also multiple for-loops:
>>>[(x,c) for x in (1, 2) for c in "abc"]
[(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c')]

That last one is close to:

for x in (1, 2):
for c in "abc":
(x, c)

Thank you. I think that clears up the mystery a bit. I added your note
to my snippets file. When I have a situation that I can't resolve, I'll
ask with the specifics.

I really do try to learn this as much as possible on my own without just
flinging a question onto the forum.
Oct 20 '08 #5
Pat
Diez B. Roggisch wrote:
Pat wrote:
>I have written chunks of Python code that look this:

new_array = []
for a in array:
if not len( a ):
continue
new_array.append( a )

new_array = [a for a in array if len(a)]
>and...

string = ""
for r in results:
if not r.startswith( '#' ):
string =+ r


"".join(r for r in results if not r.startswith("#"))

Diez

Thank you very much! That's exactly what I was looking for. That's
much cleaner than my code.

This is a great forum and I really appreciate everyone's help.
Oct 20 '08 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Elaine Jackson | last post by:
List comprehensions don't work the way you intuitively expect them to work. I realize many people have no intuitions about how list comprehensions 'should' work, so if you recognize yourself in...
24
by: Mahesh Padmanabhan | last post by:
Hi, When list comprehension was added to the language, I had a lot of trouble understanding it but now that I am familiar with it, I am not sure how I programmed in Python without it. Now I...
9
by: Neuruss | last post by:
I have a doubt regarding list comprehensions: According to Mark Lutz in his book Learning Pyhon: "...there is currently a substantial performance advantage to the extra complexity in this case:...
42
by: Alan McIntyre | last post by:
Hi all, I have a list of items that has contiguous repetitions of values, but the number and location of the repetitions is not important, so I just need to strip them out. For example, if my...
30
by: Steven Bethard | last post by:
George Sakkis wrote: > "Steven Bethard" <steven.bethard@gmail.com> wrote: >> Dict comprehensions were recently rejected: >> http://www.python.org/peps/pep-0274.html >> The reason, of course,...
7
by: Steven Bethard | last post by:
Tom Anderson <twic@urchin.earth.li> wrote: > Sounds good. More generally, i'd be more than happy to get rid of list > comprehensions, letting people use list(genexp) instead. That would >...
6
by: Heiko Wundram | last post by:
Hi all! The following PEP tries to make the case for a slight unification of for statement and list comprehension syntax. Comments appreciated, including on the sample implementation. ===...
6
by: Lonnie Princehouse | last post by:
List comprehensions appear to store their temporary result in a variable named "_" (or presumably "_", "_" etc for nested comprehensions) In other words, there are variables being put into the...
7
by: idiolect | last post by:
Hi all - Sorry to plague you with another newbie question from a lurker. Hopefully, this will be simple. I have a list full of RGB pixel values read from an image. I want to test each RGB band...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.