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

时间:2014-05-24 12:06:13

标签: python list

我有一个如下列表:

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

我希望将所有零推到该列表的开头。结果必须如下。

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

如何在Python 2中完成?

4 个答案:

答案 0 :(得分:14)

您可以对列表进行排序:

a.sort(key=lambda v: v != 0)

key函数告诉Python按值排序值是0FalseTrue之前排序,然后根据其原始相对位置对值进行排序。

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

演示:

>>> a = [4, 5, 0, 0, 6, 7, 0, 1, 0, 5]
>>> a.sort(key=lambda v: v != 0)
>>> a
[0, 0, 0, 0, 4, 5, 6, 7, 1, 5]

答案 1 :(得分:11)

这可以在没有排序的情况下完成。

解决方案

初​​始化:

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

In [9]: from itertools import compress, repeat, chain

list.countitertools.compress

In [10]: x = [0] * a.count(0); x.extend(compress(a, a))

In [11]: x
Out[11]: [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]

list.countitertools.compressitertools.repeatitertools.chain

In [13]: list(chain(repeat(0, a.count(0)), compress(a, a)))
Out[13]: [0, 0, 0, 0, 4, 5, 6, 7, 1, 5]

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

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的解决方案往往会变慢,因为函数调用次数很多。

答案 2 :(得分:1)

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

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

然后霜冻的方法:

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

新:

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

尽管相对较慢,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

答案 3 :(得分:0)

尝试这个简单的过程: -

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]