5 Best Ways to Move Zeros to End of List in Python

Rate this post

πŸ’‘ Problem Formulation: The task at hand involves rearranging the elements of a list in such a way that all zeros are moved to the end while maintaining the relative order of the non-zero elements. For instance, given the input [0, 2, 0, 3, 4], the desired output would be [2, 3, 4, 0, 0]. This operation is to be done in-place to optimize for space efficiency.

Method 1: Using a Loop to Push Zeros

This method involves iterating over the list and pushing each zero to the end, one at a time. This is an efficient way to ensure that the order of non-zero elements stays the same.

Here’s an example:

def move_zeros(nums):
    pos = 0
    for i in nums:
        if i != 0:
            nums[pos] = i
            pos += 1
    while pos < len(nums):
        nums[pos] = 0
        pos += 1

my_list = [0, 1, 0, 3, 12]
move_zeros(my_list)
print(my_list)

The output of this code snippet:

[1, 3, 12, 0, 0]

This loop-based method works by keeping track of the position pos where the next non-zero element should be placed. As we identify non-zero elements, we place them at the current pos and increment pos. After all non-zero elements are arranged, we fill the rest of the list with zeros.

Method 2: Using the sort() Method Custom Sort

This technique makes use of the list’s sort() method, leveraging a custom key function that ensures that zeros are considered the highest value during the sort, thereby moving them to the end of the list.

Here’s an example:

my_list = [0, 1, 0, 3, 12]
my_list.sort(key=lambda x: x == 0)
print(my_list)

The output of this code snippet:

[1, 3, 12, 0, 0]

In this snippet, the sort() method uses a lambda function as the sorting key. It returns True (which is internally treated as 1) if the element is zero and False (treated as 0) otherwise. Since True is greater than False, zeros end up at the end of the sorted list.

Method 3: Two Pointer Approach

The two-pointer approach uses two markers to process the list in a single pass. One pointer identifies non-zero elements while the other follows to place them appropriately. This method is highly efficient for large datasets.

Here’s an example:

def move_zeros(nums):
    left = 0
    for right in range(len(nums)):
        if nums[right] != 0:
            nums[left], nums[right] = nums[right], nums[left]
            left += 1
my_list = [0, 3, 1, 0, 12]
move_zeros(my_list)
print(my_list)

The output of this code snippet:

[3, 1, 12, 0, 0]

This method uses a left pointer to keep track of where the next non-zero element should go. As the right pointer finds non-zero elements, they are swapped into the correct position. This effectively shifts all zeros to the end.

Method 4: Filter and Extend

Using the filter() function to remove zeros and then extending the list with the appropriate number of zeros is both readable and concise. This method, however, creates an intermediate list of non-zero elements.

Here’s an example:

my_list = [0, 3, 1, 0, 12]
non_zeros = list(filter(lambda x: x != 0, my_list))
zeros = [0] * (len(my_list) - len(non_zeros))
my_list[:] = non_zeros + zeros
print(my_list)

The output of this code snippet:

[3, 1, 12, 0, 0]

This snippet filters out all non-zero elements and then creates a new list with the correct number of zeros. It then concatenates both lists and assigns the result back to the original list to maintain the in-place requirement.

Bonus One-Liner Method 5: List Comprehension and Count

Combine a list comprehension for non-zero elements with multiplication of zeros, using the count of zeros in the list. This one-liner is pythonic and highly readable but also generates an intermediate list before in-place assignment.

Here’s an example:

my_list = [0, 3, 1, 0, 12]
my_list[:] = [i for i in my_list if i != 0] + [0] * my_list.count(0)
print(my_list)

The output of this code snippet:

[3, 1, 12, 0, 0]

This one-liner creates a new list composed of non-zero elements followed by a series of zeros equal to the count of zeros in the original list. The slice assignment my_list[:] ensures that the original list reference is updated.

Summary/Discussion

  • Method 1: Loop to Push Zeros. Simple and straightforward. Requires multiple passes through the list.
  • Method 2: Custom Sort. Clever use of built-in methods. Relies on sort algorithm efficiency and may not be as fast as other methods.
  • Method 3: Two Pointer Approach. In-place and efficient. Can be less intuitive to readers unfamiliar with the technique.
  • Method 4: Filter and Extend. Readable and concise. Generates intermediate lists, which may be less space efficient.
  • Method 5: List Comprehension and Count. Pythonic one-liner. Like Method 4, it creates intermediate lists before in-place update.