Reputation: 623
Say I have an array:
array=[1,0,2,3,4,0,0,5,6,0]
I want a list that returns just the numbers and not zeros. So I did this and it works:
print(list(y for y in array if y!=0)
I tried another way without list comprehension and it won't work, can someone explain why?
for y in array:
if y!=0:
print(list(y))
What would be another way to print a list of just the numbers without the 0's?
Edit: I tried to solve this problem using a for loop, and it works if I make an empty list on top. It works, but I don't understand why! But why does this work and other one doesn't? What's more efficient, this or the list comprehension in terms of speed/memory?
array=[1,0,2,3,4,0,0,5,6,0]
list=[]
for y in array:
if y!=0:
list.append(y)
print(list)
Upvotes: 3
Views: 803
Reputation: 13
list() is a constructor that takes in zero parameters or an iterable, such as a list, str, or tuple. The problem is that an int is not an iterable, where as a list comprehension ([y for y in array if y!= 0]) returns an iterable and can be used to create a list Python documentation.
Upvotes: 0
Reputation: 45231
When you create a for
loop, everything in that loop - EVERYTHING - executes once for each time through the loop. So this line:
print(list(y))
...prints a new list
each trip through the loop. Whereas in the first version:
print(list(y for y in array if y!=0))
...there is only ONE thing printed: the results of the list()
comprehension.
EDIT: If you want to fix the 'int' object is not iterable
error in the second version, you can do it this way:
for y in array:
if y!=0:
print([y])
The list
function requires an iterable object as input. An integer is not iterable, so we surround it with brackets to put it inside a list
instead, which essentially does the same thing. Use the version above and you'll see that a new list
is created each time through the loop.
Upvotes: 1
Reputation:
Lets take a good look at what you thought was right:
for y in array:
if y!=0:
print(list(y))
So we go through every value in the array. If the value isn't zero, we print list(y)
. The problem starts here. Because y
is a integer, list(y)
returns an error, because you can't convert an integer into a list. It would work if you did print(y)
.
But then comes another problem. If we print every element of the list which isn't a zero, we get something like this, because that code would only print in order:
1
2
3
4
5
6
You state in your question that you wanted a list. So this code wouldn't work either, because there would be no stored list. So we finally arrive to the right answer:
array=[1,0,2,3,4,0,0,5,6,0]
list=[]
for y in array:
if y!=0:
list.append(y)
print(list)
This answer stores each y
value which isn't zero in a list, then finally prints out the list.
EDIT:
This is how the list comprehension works:
First of all, I can't help but observe that you have made a syntax error. :P You forgot an ending parantheses! Here's the correct code:
print(list(y for y in array if y != 0))
.
Second of all, I need to state that that is NOT A LIST COMPREHENSION. That is a generator. There is a tiny difference.
A list comprehension generates the list on the spot. A list comprehension looks like this: [y for y in array if y != 0]
A generator, which is what you used above, is an expression is stored. It looks like this: y for y in array if y != 0
.
So instead of using list(y for y in array if y != 0
, you can directly go to [y for y in array if y != 0]
.
So now I will explain how the "list comprehension" (generator expression) actually works. It starts out by looping through each value of array
. It checks if the value is not a zero. If it isn't, it adds y
to the output list. So basically, the generator expression is the same as the second working code with the for loop, except python creates the output list for you, adding some convenience.
Upvotes: 3
Reputation: 2244
With your second attempt, you had list(y)
where you should've had y
. As y
is a single int and not an iterable, list(y)
fails. This is the output:
>>> array=[1,0,2,3,4,0,0,5,6,0]
>>> print(list(y for y in array if y!=0))
[1, 2, 3, 4, 5, 6]
>>> for y in array:
if y!=0:
print(list(y))
Traceback (most recent call last):
File "<pyshell#49>", line 3, in <module>
print(list(y))
TypeError: 'int' object is not iterable
>>> for y in array:
if y!=0:
print(y)
1
2
3
4
5
6
Another way is to use filter
, like so:
>>> print(list(filter(bool,array)))
[1, 2, 3, 4, 5, 6]
filter
takes a function and iterable, applies the function to each item in the iterable, and returns only the ones where the function returned a truthy value. As bool
is False if y is 0 (falsy) and True otherwise, it works perfectly for these purposes. Still, it may be useful to you to see that you can also do it this way:
>>> print(list(filter(lambda x:x != 0, array)))
[1, 2, 3, 4, 5, 6]
I see you were also wondering why the first version worked.
>>> print(list(y for y in array if y!=0))
Here, for y in array
is a generator, a special kind of Python object that spits out one value every time you ask it for one, so to speak. So let me break it down this way:
print( ) #Print
list( ) #Convert iterable to list
for y in array #For each y in array...
if y!=0 #If y is not zero...
y #Include y in the iterable for list()
Does that help?
Upvotes: 1
Reputation: 5261
If you want to do it with a for
loop you need to do something like this:
nonzero = []
for y in array:
if y != 0:
nonzero.append(y)
print(nonzero)
but a list comprehension or a filter
will be better, both in terms of readability and in terms of speed.
Upvotes: 1