Clone List Items

Let's say I have a Python list that looks like this:

list = [ a, b, c, d]

I am looking for the most efficient execution method to get this:

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

So, if the list contains N elements, then the first element is cloned N-1 times, the second element N-2 times, etc ... the last element is cloned NN times or 0 times. Any suggestions on how to do this effectively on large lists.

+3
source share
10 answers

How about this - Simple

>>> 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
source

Please note that I am testing speed, not correctness. If someone wants to edit in unit test, I will approach him.

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

. - , , , . .

, .

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

, , , enumerate, , .

+5
>>> 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, . . ( , j . .)

, enumerate xrange.

+4

Lazy mode:

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)))
+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
+2

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']
+1

: O (1) O (N ^ 2) cpu, , , O (N ^ 2) . , , , . , .

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

, list = [ a, a, a, a, b, b, b, c, c, d ] O (4n) = O (n), n 4n . aaronasterling .

You can trick and simply not create a new list. Just enter the index value as input. Divide the index value by 4. Use the result as the index value of the source list.

In pseudo code:

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.
}
0
source

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']
0
source
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))]

untested, but I think it will work

-1
source

Source: https://habr.com/ru/post/1777262/


All Articles