克隆列表的元素

时间:2010-11-28 05:03:18

标签: python

假设我有一个如下所示的Python列表:

list = [ a, b, c, d]

我正在寻找最有效的方式来获得这个:

list = [ a, a, a, a, b, b, b, c, c, d ]

因此,如果列表长度为N个元素,则第一个元素被克隆N-1次,第二个元素被克隆N-2次,依此类推......最后一个元素被克隆N-N次或0次。有关如何在大型列表上有效执行此操作的任何建议。

10 个答案:

答案 0 :(得分:5)

请注意,我正在测试速度,而不是正确性。如果有人想在单元测试中编辑,我会解决它。

pyfunc_fastest: 152.58769989 usecs
pyfunc_local_extend: 154.679298401 usecs
pyfunc_iadd: 158.183312416 usecs
pyfunc_xrange: 162.234091759 usecs
pyfunc: 166.495800018 usecs
Ignacio: 238.87629509 usecs
Ishpeck: 311.713695526 usecs
FabrizioM: 456.708812714 usecs
JohnKugleman: 519.239497185 usecs
Bwmat: 1309.29429531 usecs

测试代码here。第二次修订是垃圾,因为我急于让我的第一批测试后发布的每个人都经过测试。这些时间是代码的第五次修订。

这是我能够获得的最快版本。

def pyfunc_fastest(x):
    t = []
    lenList = len(x)
    extend = t.extend
    for l in xrange(0, lenList):
        extend([x[l]] * (lenList - l))

奇怪的是,我修改的一个版本是为了避免使用enumerate索引到列表中而比原始版本慢。

答案 1 :(得分:4)

>>> items = ['a', 'b', 'c', 'd']

>>> [item for i, item in enumerate(items) for j in xrange(len(items) - i)]
['a', 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd']

首先,我们使用enumerate同时提取索引和值。然后我们使用嵌套的for循环迭代每个项目减少次数。 (请注意,永远不会使用变量j。它是垃圾。)

由于使用enumeratexrange生成器,这应该接近最佳,内存使用量最少。

答案 2 :(得分:3)

这个怎么样 - 一个简单的

>>> x = ['a', 'b', 'c', 'd']
>>> t = []
>>> lenList = len(x)
>>> for l in range(0, lenList):
...     t.extend([x[l]] * (lenList - l))
... 

>>> t
['a', 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd']
>>> 

答案 3 :(得分:2)

懒惰模式:

import itertools

l = ['foo', 'bar', 'baz', 'quux']

for i in itertools.chain.from_iterable(itertools.repeat(e, len(l) - i)
    for i, e in enumerate(l)):
  print i

如果确实需要列表,请将其推过list()

list(itertools.chain.from_iterable(itertools.repeat(e, len(l) - i)
  for i, e in enumerate(l)))

答案 4 :(得分:2)

我的第一直觉......

l = ['a', 'b', 'c', 'd']
nl = []

i = 0

while len(l[i:])>0:
    nl.extend( [l[i]]*len(l[i:]) )
    i+=1

print nl

答案 5 :(得分:1)

诀窍在于使用itertools的重复

from itertools import repeat

alist = "a b c d".split()
print [ x  for idx, value in enumerate(alist) for x in repeat(value, len(alist) - idx) ]

>>>['a', 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd']

答案 6 :(得分:1)

使用生成器:它是O(1)内存和O(N ^ 2)cpu,不同于产生使用O(N ^ 2)内存 cpu的最终列表的任何解决方案。这意味着只要输入列表足够大以使构造的列表填充内存并开始交换,它就会大大加快。除非这是家庭作业,否则你不太可能需要将最终列表留在内存中。

def triangle(seq):
    for i, x in enumerate(seq):
        for _ in xrange(len(seq) - i - 1):
            yield x

答案 7 :(得分:0)

要创建新列表,list = [ a, a, a, a, b, b, b, c, c, d ]将需要O(4n)= O(n)时间,因为对于每n个元素,您在第二个数组中创建4n个元素。 aaronasterling给出了线性解决方案。

你可以作弊而不是创建新列表。简单地说,获取索引值作为输入。将索引值除以4.使用结果作为原始列表的索引值。

在伪代码中:

function getElement(int i)
{
     int trueIndex = i / 4;
     return list[trueIndex]; // Note: that integer division will lead us to the correct index in the original array.
}

答案 8 :(得分:0)

FWIW:

>>> lst = list('abcd')
>>> [i for i, j in zip(lst, range(len(lst), 0, -1)) for _ in range(j)]
['a', 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd']

答案 9 :(得分:-1)

def gen_indices(list_length):
    for index in range(list_length):
        for _ in range(list_length - index):
            yield index

new_list = [list[i] for i in gen_indices(len(list))]

未经测试,但我认为它会起作用