如何将python列表或numpy数组中的所有非零元素移动到一边?

时间:2014-11-17 06:38:07

标签: python list numpy

我要对list或numpy数组进行以下操作:

[0, 0, 0, 1, 0, 0, 4, 2, 0, 7, 0, 0, 0]

将所有非零移动到右侧:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 2, 7]

我怎样才能有效地做到这一点?

由于

============

抱歉,我没说清楚,我需要非零元素的顺序。

2 个答案:

答案 0 :(得分:6)

您可以按列表值对列表进行排序。所有虚假值(数字只为零)将被推到列表的前面。 Python的内置排序看起来很稳定,因此其他值将保持其相对位置。

示例:

>>> a = [0, 0, 0, 1, 0, 0, 5, 2, 0, 7, 0, 0, 0]
>>> sorted(a, key=bool)
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 2, 7]

答案 1 :(得分:3)

使用NumPy:

>>> a = np.array([0, 0, 0, 1, 0, 0, 4, 2, 0, 7, 0, 0, 0])
>>> np.concatenate((a[a==0], a[a!=0]))
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 2, 7])

您可以在O(N)时间在Python中执行此操作,也可以使用简单的for循环。但是,通过使用a.sort(key=bool)

,我们可以在@ grc的解决方案中采取一些额外的内存
>>> from collections import deque
#Using a deque
>>> def solve_deque(lst):
    d = deque()
    append_l = d.appendleft
    append_r = d.append
    for x in lst:
        if x:
            append_r(x)
        else:
            append_l(x)
    return list(d) #Convert to list if you want O(1) indexing.
...
#Using simple list
>>> def solve_list(lst):                           
    left = []                                    
    right = []
    left_a = left.append
    right_a = right.append
    for x in lst:
        if x:
            right_a(x)
        else:
            left_a(x)
    left.extend(right)
    return left

>>> solve_list([0, 0, 0, 1, 0, 0, 4, 2, 0, 7, 0, 0, 0])
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 2, 7]
>>> solve_deque([0, 0, 0, 1, 0, 0, 4, 2, 0, 7, 0, 0, 0])
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 2, 7]