Ali
Ali

Reputation: 1041

While in a for loop

I want to know the number of zeros which first appear in a list, before any other number.

For example:
L1 = [0, 0, 0, 0, 0, 1, 2] - the output should be 5, which is the number of zeros.
L2 = [1, 0, 0, 0, 0, 0, 2] - the output should be zero. Although there are 5 zeros in this list but the list starts with 1.

Here is my code:

k = 0
for i in L1:
    while i == 0:
        k = k + 1

It doesn't work though. I think it is an infinite loop, but I don't know why.

Upvotes: 1

Views: 192

Answers (4)

mbdavis
mbdavis

Reputation: 4010

What you're thinking while does, is carry on as normal until the condition isn't met. What it really does, is repeat the code inside of the while as a loop until the condition isn't met.

Here's my solution, which tries to work as similarly to yours as possible, by carrying on counting until the number isn't a 0 then looking at how far it's come and breaking out of the for loop.

k = 0
for index,item in enumerate(L1):
    if item != 0:
        k = len(L1[:index])
        break

Upvotes: 0

paxdiablo
paxdiablo

Reputation: 881453

Think of what will happen the first time i gets set to 0.

The while loop will start and never stop, because i is not changed within that loop.

You would be better off with something as per the following transcript, a slight modification of yours:

>>> list1 = [0,0,0,0,0,1,2]
>>> count = 0
>>> for item in list1:
...     if item == 0:
...         count = count + 1
...     else:
...         break
... 
>>> print count
5

or the slightly shorter variation which breaks immediately for a non-zero value, adding one otherwise.:

>>> list1 = [0,0,0,0,0,1,2]
>>> count = 0
>>> for item in list1:
...     if item != 0: break
...     count = count + 1
... 
>>> print count
5

Upvotes: 5

Mark R. Wilkins
Mark R. Wilkins

Reputation: 1302

My answer expands on paxdiablo's. Thanks to him for clarifying OP's intent with the L2 case, which I had misread.

While itertools is handy for this kind of thing, at the point you're at, I'd say mastering the basic language features is worthwhile.

In your code, you do this:

L1 = [0, 0, 0, 0, 0, 1, 2]

k = 0
for i in L1:
    while i == 0:
        k = k + 1

When you run that chunk of code on L1, it loops forever. Here's why:

for causes the code that's enclosed (meaning the code below that's set aside by indentation) to loop. So, your for i in L1: loop runs everything indented below it once for each thing in L1.

But, while does something similar. while tells Python to run the indented code below it over and over until the condition on the while statement is False.

So, in the case of L1, the first time through the for loop, i gets set to 0. Then, while i == 0: says to execute the code enclosed, k = k + 1, over and over again until i is no longer zero. Unfortunately, since the code in the while loop does not change the value of i, i will be zero until the end of time, so it runs forever, repeatedly adding one to k.

What you're looking for is an if statement, which will not loop. It will just run the enclosed code, or not, based on whether its test is true. So, instead of:

    while i == 0:
        k = k + 1

you can use

    if i == 0:
        k = k + 1
    else:
        break

Then, each time through the for loop, the code asks whether i is zero, and if so, only once, it adds one to k, then goes on to the next list element. To cover your L2 case, if you hit a number that is not zero, break exits the for loop and stops counting.

The answer presented with itertools is clever, useful, good to know, and probably what you'd want to use for very large lists, but since it appears you're just learning the language (and probably learning your first language), it's worth learning how to use for, while, and if correctly.

Upvotes: 0

Christian Schramm
Christian Schramm

Reputation: 304

As other commentators have said, the problem in your code is that you seem to misunderstand the meaning of the while keyword. That aside, for problems like these, I often prefer a more functional style:

>>> import itertools
>>> k = len(list(itertools.takewhile(lambda x: x == 0, L1)))
>>> k
5
>>> k = len(list(itertools.takewhile(lambda x: x == 0, L2)))
>>> k
0

If you are just beginning to get to know Python, playing around with what the itertools offers is well worth it.

Upvotes: 2

Related Questions