Simple newbie question

A

Angelo Secchi

Hi,
I'm trying to remove lines with zeros from a list "lista".
The code i'm using is the following:

for line in lista:
if sum(line == 0) > 0:
lista.remove(line)


The problem is that the loop stops at the first line with zeros and it
doesn't remove the other lines with zeros (at least if I do not re-run
the loop). Probably I do not understand how the loop works.

Any help ?

Thanks,

Angelo
 
D

Duncan Booth

The code i'm using is the following:

for line in lista:
if sum(line == 0) > 0:
lista.remove(line)


The problem is that the loop stops at the first line with zeros and it
doesn't remove the other lines with zeros (at least if I do not re-run
the loop). Probably I do not understand how the loop works.

The loop will assign the first element of lista to line, then the second,
then the third, and so on.

The problem is that, if you remove an element everything after it shifts up
one place. Say you are looking at the first element and remove it, what was
the second element now becomes the first element, but the next time round
the loop you will look at the new second element and the one that was
originally second (and is now first) will be skipped.

The solution is never to work on the list you are modifying. Just make a
copy of the list and iterate over the copy, that means you can safely
modify the original. To copy a list, use the 'list' builtin.

for line in list(lista):
if condition:
lista.remove(line)

Alternatively turn your brain around and instead of deleting specific
elements from the list just build a new list with the elements you want to
keep. In this case you could do that using a list comprehension:

lista = [ line for line in lista if not condition ]

(Obviously in both these cases replace condition with the correct
expression, which as Gerhard pointed out may not be the condition in your
original posting.)

The list comprehension rebinds the lista variable, whereas your original
attempt was modifying the list inplace. This might be significant if there
are other references to the same list elsewhere in your code. If it does
matter, then you can still use a list comprehension to mutate the original
list:

lista[:] = [ line for line in lista if not condition ]

Unlike the original 'for' loop, this works by building a complete
replacement list then mutating the original list in one go.
 
A

Angelo Secchi

Thanks a lot to everybody.
Your points have been very useful.
Angelo



The code i'm using is the following:

for line in lista:
if sum(line == 0) > 0:
lista.remove(line)


The problem is that the loop stops at the first line with zeros and
it doesn't remove the other lines with zeros (at least if I do not
re-run the loop). Probably I do not understand how the loop works.

The loop will assign the first element of lista to line, then the
second, then the third, and so on.

The problem is that, if you remove an element everything after it
shifts up one place. Say you are looking at the first element and
remove it, what was the second element now becomes the first element,
but the next time round the loop you will look at the new second
element and the one that was originally second (and is now first) will
be skipped.

The solution is never to work on the list you are modifying. Just make
a copy of the list and iterate over the copy, that means you can
safely modify the original. To copy a list, use the 'list' builtin.

for line in list(lista):
if condition:
lista.remove(line)

Alternatively turn your brain around and instead of deleting specific
elements from the list just build a new list with the elements you
want to keep. In this case you could do that using a list
comprehension:

lista = [ line for line in lista if not condition ]

(Obviously in both these cases replace condition with the correct
expression, which as Gerhard pointed out may not be the condition in
your original posting.)

The list comprehension rebinds the lista variable, whereas your
original attempt was modifying the list inplace. This might be
significant if there are other references to the same list elsewhere
in your code. If it does matter, then you can still use a list
comprehension to mutate the original list:

lista[:] = [ line for line in lista if not condition ]

Unlike the original 'for' loop, this works by building a complete
replacement list then mutating the original list in one go.

--
Duncan Booth
(e-mail address removed) int month(char
*p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3""\6\7\xb\1\x
9\xa\2\0\4"];} // Who said my code was obscure?--
http://mail.python.org/mailman/listinfo/python-list
 
D

Dang Griffith

I'm trying to remove lines with zeros from a list "lista".
The code i'm using is the following:

for line in lista:
if sum(line == 0) > 0:
lista.remove(line)


The problem is that the loop stops at the first line with zeros and it
doesn't remove the other lines with zeros (at least if I do not re-run
the loop). Probably I do not understand how the loop works.
I see other's responses, but am wondering why the line

if sum(line == 0) > 0:

doesn't raise a "TypeError: iteration over non-sequence" for everyone
else. line==0 is a single boolean, and a sum on that raises an
exception for me.

I'm also wondering why the program compiles, since the

lista.remove(line)

should be more indented.

Thanks,
--dang
 

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
474,172
Messages
2,570,933
Members
47,473
Latest member
ChristelPe

Latest Threads

Top