在Python中,将所有零移到列表的开头

在Python中,将所有零移到列表的开头,python,list,Python,List,我的清单如下: a = [4, 5, 0, 0, 6, 7, 0, 1, 0, 5] 我想把所有的零放到列表的开头。结果必须如下所示 a = [0, 0, 0, 0, 4, 5, 6, 7, 1, 5] 如何在Python2中执行此操作?您可以对列表进行排序: a.sort(key=lambda v: v != 0) 键函数告诉Python按值是否为0对值进行排序False在True之前排序,然后根据其原始相对位置对值进行排序 对于0,返回False,首先对所有这些值进行排序。对于其余的T

我的清单如下:

a = [4, 5, 0, 0, 6, 7, 0, 1, 0, 5]
我想把所有的零放到列表的开头。结果必须如下所示

a = [0, 0, 0, 0, 4, 5, 6, 7, 1, 5]

如何在Python2中执行此操作?

您可以对列表进行排序:

a.sort(key=lambda v: v != 0)
函数告诉Python按值是否为
0
对值进行排序
False
True
之前排序,然后根据其原始相对位置对值进行排序

对于
0
,返回
False
,首先对所有这些值进行排序。对于其余的
True
,返回sort,将它们放在最后,但保持它们的相对位置不变

演示:


无需排序即可完成此操作

解决 初始化:

In [8]: a = [4, 5, 0, 0, 6, 7, 0, 1, 0, 5]

In [9]: from itertools import compress, repeat, chain
列表.计数

与之前相同,但没有
列表。计数

In [12]: c = list(compress(a, a)); [0] * (len(a) - len(c)) + c
Out[12]: [0, 0, 0, 0, 4, 5, 6, 7, 1, 5]
In [14]: c = list(compress(a, a)); list(chain(repeat(0, len(a) - len(c)), c))
Out[14]: [0, 0, 0, 0, 4, 5, 6, 7, 1, 5]
列表.计数

与前一个相同,但没有
list.count

In [12]: c = list(compress(a, a)); [0] * (len(a) - len(c)) + c
Out[12]: [0, 0, 0, 0, 4, 5, 6, 7, 1, 5]
In [14]: c = list(compress(a, a)); list(chain(repeat(0, len(a) - len(c)), c))
Out[14]: [0, 0, 0, 0, 4, 5, 6, 7, 1, 5]
基准 对于小型列表:

In [21]: %timeit x = [0] * a.count(0); x.extend(compress(a, a))
1000000 loops, best of 3: 583 ns per loop

In [22]: %timeit c = list(compress(a, a)); [0] * (len(a) - len(c)) + c
1000000 loops, best of 3: 661 ns per loop

In [23]: %timeit list(chain(repeat(0, a.count(0)), compress(a, a)))
1000000 loops, best of 3: 762 ns per loop

In [24]: %timeit c = list(compress(a, a)); list(chain(repeat(0, len(a) - len(c)), c))
1000000 loops, best of 3: 900 ns per loop
对于大型列表:

In [28]: a *= 10000000

In [29]: %timeit x = [0] * a.count(0); x.extend(compress(a, a))
1 loops, best of 3: 1.43 s per loop

In [30]: %timeit c = list(compress(a, a)); [0] * (len(a) - len(c)) + c
1 loops, best of 3: 1.37 s per loop

In [31]: %timeit list(chain(repeat(0, a.count(0)), compress(a, a)))
1 loops, best of 3: 1.79 s per loop

In [32]: %timeit c = list(compress(a, a)); list(chain(repeat(0, len(a) - len(c)), c))
1 loops, best of 3: 1.47 s per loop

如您所见,在某些情况下,基于itertools的解决方案往往较慢,因为函数调用数量较多。

以下是一些更好的计时方法,有两种新方法:

SETUP="
from itertools import compress, repeat, chain
a = [4, 5, 0, 0, 6, 7, 0, 1, 0, 5]
"
首先是排序:

python -m timeit -s "$SETUP" "a.sort(key=bool)"
# 1000000 loops, best of 3: 1.51 usec per loop
然后是frostnational的方法:

python -m timeit -s "$SETUP" "list(chain(repeat(0, a.count(0)), compress(a, a)))"
# 1000000 loops, best of 3: 1.16 usec per loop

python -m timeit -s "$SETUP" "cs = list(compress(a, a)); list(chain(repeat(0, len(a)-len(cs)), cs))"
# 1000000 loops, best of 3: 1.37 usec per loop
然后是更直接地从列表中工作的方法:

python -m timeit -s "$SETUP" "[0] * a.count(0) + list(filter(bool, a))"
# 1000000 loops, best of 3: 1.04 usec per loop

python -m timeit -s "$SETUP" "nonzero = list(filter(bool, a)); [0] * (len(a)-len(nonzero)) + nonzero"
# 1000000 loops, best of 3: 0.87 usec per loop
同样,对于较大尺寸的输入:

SETUP="
from itertools import compress, repeat, chain
a = [4, 5, 0, 0, 6, 7, 0, 1, 0, 5] * 1000
"
分类:

python -m timeit -s "$SETUP" "a.sort(key=bool)"
# 1000 loops, best of 3: 1.08 msec per loop
frostnational的:

python -m timeit -s "$SETUP" "list(chain(repeat(0, a.count(0)), compress(a, a)))"
# 1000 loops, best of 3: 333 usec per loop

python -m timeit -s "$SETUP" "cs = list(compress(a, a)); list(chain(repeat(0, len(a)-len(cs)), cs))"
# 1000 loops, best of 3: 206 usec per loop
新的:

也就是说,尽管相对较慢,但Martijn Pieters使用排序的决定对于大小合理的列表来说实际上是相当有竞争力的,过早的优化是所有问题的根源


FWIW,下面是一些很长列表的时间安排:

SETUP="
from itertools import compress, repeat, chain
a = [4, 5, 0, 0, 6, 7, 0, 1, 0, 5] * 1000000
"
python -m timeit -s "$SETUP" "a.sort(key=bool)"
# 10 loops, best of 3: 1.21 sec per loop

python -m timeit -s "$SETUP" "list(chain(repeat(0, a.count(0)), compress(a, a)))"
# 10 loops, best of 3: 347 msec per loop

python -m timeit -s "$SETUP" "cs = list(compress(a, a)); list(chain(repeat(0, len(a)-len(cs)), cs))"
# 10 loops, best of 3: 226 msec per loop

python -m timeit -s "$SETUP" "[0] * a.count(0) + list(filter(bool, a))"
# 10 loops, best of 3: 310 msec per loop

python -m timeit -s "$SETUP" "nonzero = list(filter(bool, a)); [0] * (len(a)-len(nonzero)) + nonzero"
# 10 loops, best of 3: 153 msec per loop
尝试以下简单过程:-
顺序重要吗???如果没有,您可以只使用.sort()。是否可以保证排序是稳定的?据我所知,语言文档没有提到它。@viraptor:是的,排序保证是稳定的。@viraptor:我喜欢这种方法的简单性,但对于较大的列表,请记住排序算法通常具有计算时间复杂性n ln n。在线性时间(n)内,将所有零移到列表末尾应该是可能的-请参阅其他答案。@Messa:注意,该解决方案在列表中循环两次。一次用于
a.count(0)
调用,另一次用于筛选列表。列表乘法和串联的成本也需要考虑在内。实际上,我希望排序能够获胜。当列表包含
None
False
时,排序会做什么
None
False
都是falsy,因此它们都将被替换为零。但是原始列表只包含数字,所以我认为这不是问题;x+=压缩(a,a)
,在我的机器上,在所有情况下都会更快。也就是说,您的基准测试并不真正公平,因为由于列表的附加副本,排序(a,…)
比排序(…)慢,并且您将使用
key=bool
而不是
key=lambda x:x!=0
如果您试图优化速度。
python -m timeit -s "$SETUP" "[0] * a.count(0) + list(filter(bool, a))"
# 1000 loops, best of 3: 295 usec per loop

python -m timeit -s "$SETUP" "nonzero = list(filter(bool, a)); [0] * (len(a)-len(nonzero)) + nonzero"
# 10000 loops, best of 3: 143 usec per loop
SETUP="
from itertools import compress, repeat, chain
a = [4, 5, 0, 0, 6, 7, 0, 1, 0, 5] * 1000000
"
python -m timeit -s "$SETUP" "a.sort(key=bool)"
# 10 loops, best of 3: 1.21 sec per loop

python -m timeit -s "$SETUP" "list(chain(repeat(0, a.count(0)), compress(a, a)))"
# 10 loops, best of 3: 347 msec per loop

python -m timeit -s "$SETUP" "cs = list(compress(a, a)); list(chain(repeat(0, len(a)-len(cs)), cs))"
# 10 loops, best of 3: 226 msec per loop

python -m timeit -s "$SETUP" "[0] * a.count(0) + list(filter(bool, a))"
# 10 loops, best of 3: 310 msec per loop

python -m timeit -s "$SETUP" "nonzero = list(filter(bool, a)); [0] * (len(a)-len(nonzero)) + nonzero"
# 10 loops, best of 3: 153 msec per loop
from collections import deque
a = [4, 5, 0, 0, 6, 7, 0, 1, 0, 5]
b = deque([x for x in a if x!=0])
for i in a:
    if i==0:
        b.appendleft(0)
print list(b)
#output -> [0, 0, 0, 0, 4, 5, 6, 7, 1, 5]