Home > other >  How can I move zeroes to the end of a list?
How can I move zeroes to the end of a list?

Time:06-04

I have an array of integers like:

nums = [0, 1, 0, 3, 12]

I want to move all '0's to the end of it, while maintaining the relative order of the non-zero elements. So the desired output is [1, 3, 12, 0, 0].

I made the following attempts:

temp = 0
for i in range(len(nums)):
    if nums[i] == 0:
        nums.pop(i)
        temp  = 1
print(temp)

In this code, I got an error saying that nums[i] has an index out of range. Why? len(nums) == 5, so the i values should all be valid.

nums = [0,1,0,3,12]
nums.sort()
temp = 0
for i in range(len(nums)-1):
    if nums[i] == 0:
        print(nums[i])
        temp  =1
        nums.pop(i)
print(nums)
for _ in range(temp):
    nums.append(0)
print(nums)

With this code, the first print gives an output of [0, 1, 3, 12], so in the final result, not all of the zeroes are moved. Why were they not all popped by the first loop?

CodePudding user response:

I think one way you can get the desired output is to separate the nums list into two list that doesn't contain zeros and one does using list comprehension and concat the two list together

nums = [0,1,0,3,12]
new_list = [n for n in nums if n != 0]   [n for n in nums if n == 0]

Edit: per @DanielHao's suggestion, you can also use sorted key lambda with lambda x: not x which will then interprets zeroes as 1 and non-zeroes as 0 when sorting the list

nums = [0,1,0,3,12]
nums[:] = sorted(nums, key=lambda x: not x)

CodePudding user response:

Q1) When you pop out the item, the length of nums is decreased. For loops will not adjust the range being iterated over, so in this case range(len(nums)) will always be range(5) as this was the original length. This means that nums[4] is called, which results in an index error because the item that used to be at this index has moved backwards in the list due to the removal of prior values.

A solution is to use a while loop, as the condition i < len(nums) will be checked at every iteration. You will have to manually increment i.

Q2) If the indices of values in the list decreases as items are popped, some values will be skipped.

A solution in tandem with a while loop is to only increment i if the condition nums[i] == 0 is not met.

nums = [0,1,0,3,12]
nums.sort()
temp = 0
i = 0
while i < len(nums)
    if nums[i] == 0:
        print(nums[i])
        temp  = 1
        nums.pop(i)
    else:
        i  = 1
print(nums)
for _ in range(temp):
    nums.append(0)
print(nums)

There are definitely easier ways to solve the same problem, as shown in other solutions, but I hope this way is easy to understand.

CodePudding user response:

1] You are popping the list element so the list length changes hence getting out of index error

2] Code:

nums = [0,1,0,3,12]
# Get count of 0's
count = nums.count(0)
# List without 0's
nums = [ i for i in nums if i!=0 ]
# Add 0's to the end 
[nums.append(0) for i in range(count)]
print(nums)
  • Related