在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]