假设我有一个如下所示的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次。有关如何在大型列表上有效执行此操作的任何建议。
答案 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
。它是垃圾。)
由于使用enumerate
和xrange
生成器,这应该接近最佳,内存使用量最少。
答案 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))]
未经测试,但我认为它会起作用