Why is this code removing `False` from the array?

111 views Asked by At

This is the task:

Write an algorithm that takes an array and moves all of the zeros to the end, preserving the order of the other elements

What is wrong with this code? Why is it not keeping boolean values while iterating through the list and removing zeros? Is it because False is equal to 0?

move_zeros([False,1,2,0,1,0,1,0,3,0,1])

def move_zeros(array):
    count=0
    for num in array:
        if num == 0:
            count +=1
            array.remove(0)
            
    return array +[0]*count
5

There are 5 answers

0
Vijeth Rai On
x = len(lis)
y = []
for i in range(len(lis)):
    if lis[i]!=0:
        y.append(lis[i])
if len(y)!=len(lis):
    z = len(lis)-len(y)
    for i in range(z):
        y.append(0)

Seems like its a homework problem. Happy to help tho.

Edit: use print(y) and you'll get what you want

0
ncasale On

Yes, False == 0 will evaluate to True in Python which is why False values are being removed from your array.

In Python, True and False are implemented as singletons, meaning all False values point to the same instance. Therefore, you can use the is operator to check if a value is exactly equal to this singleton.

False is 0 will return False, while False == 0 will return True.

3
revliscano On

Yes, indeed False == 0. Actually, bool is a subtype of int. If you want to strictly compare if False is equal to 0, then another comparison should be added to the if statement.

Also, do not modify a list while you are iterating over itself. Create a new one instead.

def move_zeros(list_):
    result = []
    zeros = 0
    for item in list_:
        if item == 0 and type(item) == int:
            zeros += 1
            continue
        result.append(item)
    return result + [0] * zeros

3
Corey Smith On

Yes 0 evaluates to False and 1 evaluates to True, use this

def move_zeros(obj):
    new_list = []
    zeros_list = []
    for item in obj:
        if item != 0 or is False:
            new_list.append(item)
        else:
            zeros_list.append(item)
    new_list.extend(zero_list)
    return new_list

This adds all non 0 to one list and all 0's to another, then returns the new_list after iterating over the zeros_list and adding them to the end of the new_list

0
MarianD On

There are 2 issues in your code:

  1. You directly changed the list over which you iterate — it is always dangerous.
  2. Other answers explained to you why False == 0 is True.

I made as few changes in your code as it was possible to fix these issues:

  1. I created a new, empty array, and instead of removing “bad” elements from the original list, I appended the “good” ones to that new array.

  2. I tested a current element for its type, too.


def move_zeros(array):
    count=0
    new_array = []
    for num in array:
        if num == 0 and type(num) is int:
            count +=1
        else:
            new_array.append(num)

    return new_array + [0]*count

Test:

move_zeros([False,1,2,0,1,0,1,0,3,0,1])
[False, 1, 2, 1, 1, 3, 1, 0, 0, 0, 0]