Insert items from list to another list every n positions

混江龙づ霸主 提交于 2021-02-07 21:54:31

问题


I have the following list.

vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
inserted_elements = [2, 2, 2, 2, 2]

I want to get the following by inserting every two elements.

output = [1, 2, 2, 3, 4, 2, 5, 6, 2, 7, 8, 2, 9, 10, 2]

Not only the Python list but also the answer using numpy array is fine.


回答1:


Here's an itertools based approach, which also works for an arbitrary number of elements to be inserted from one list to the other. For this I've defined a generator function, which will insert and element from l2 into l1 every i items:

def insert_every_n(l1, l2, k):
    i1, i2 = iter(l1), iter(l2)
    while True:
        try:
            yield from islice(i1, k)
            yield next(i2)
        except StopIteration:
            return

This works by yielding up to i items from the iterator l1 on each iteration by using itertools.islice. With yield from we are yielding as many items as there are in the sliced iterable, so the iterable is run to exhaustion, (a shortcut for for v in g: yield v).

Finally we can wrap the yield statements with a try/expect to catch the StopIteration warning.


Let's try with the proposed example:

vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
inserted_elements = [2, 2, 2, 2, 2]

list(insert_every_n(vector, inserted_elements, k=2))
# [1, 2, 2, 3, 4, 2, 5, 6, 2, 7, 8, 2, 9, 10, 2]

And if we wanted to add an item of l2 every 3 items:

vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
inserted_elements = [2, 2, 2, 2]

list(insert_every_n(vector, inserted_elements, k=3))
# [1, 2, 3, 2, 4, 5, 6, 2, 7, 8, 9, 2, 10, 2]



回答2:


numpy array step:

1.

>>> a=np.reshape(np.matrix([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),(5, 2))
>>> a
matrix([[ 1,  2],
        [ 3,  4],
        [ 5,  6],
        [ 7,  8],
        [ 9, 10]])

2.

>>> b=np.reshape(np.matrix([2, 2, 2, 2, 2]),(5, 1))
>>> b
matrix([[2],
        [2],
        [2],
        [2],
        [2]])

3.

>>> M = np.append(a, b, axis=1)
>>> M
matrix([[ 1,  2,  2],
        [ 3,  4,  2],
        [ 5,  6,  2],
        [ 7,  8,  2],
        [ 9, 10,  2]])

4.

>>> result=np.array(M).flatten()
>>> result
array([ 1,  2,  2,  3,  4,  2,  5,  6,  2,  7,  8,  2,  9, 10,  2])



回答3:


A traditional for-loop approach might look like as follows, where you pick 2 elements from vector and 1 element from inserted_elements and make the output list

vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
inserted_elements = [2, 2, 2, 2, 2]

output = []

#Pick two elements from vector and one element from inserted_elements and add it to output list
for idx in range(0,len(vector),2):

    output.extend(vector[idx:idx+2] + [inserted_elements[int(idx/2)]])

print(output)

The same thing in list-comprehension will be

output = [ v for idx in range(0,len(vector),2) for v in vector[idx:idx+2] + [inserted_elements[int(idx/2)]]]

The output will be

[1, 2, 2, 3, 4, 2, 5, 6, 2, 7, 8, 2, 9, 10, 2]



回答4:


Here's a somewhat obscure approach - but it's faster than anything else (so far):

list(itertools.chain(*zip(*[iter(vector)]*2+[iter(inserted_elements)]))) 

It uses a 'idiom' for taking items in size n groups, [iter(alist)]*n, and itertools.chain as a way of flattening a nested list.

A deleted answer used np.insert. For this I believe insert uses masking as demonstrated below:

def foo(vector, inserted_elements):
    res = np.zeros(len(vector)+len(inserted_elements),int)  
    mask = res.astype(bool) 
    mask[2::3]=True 
    res[mask]=inserted_elements 
    res[~mask]=vector    
    return res

A variation on the np.append answer is:

np.column_stack((np.reshape(vector,(-1,2)), inserted_elements)).ravel()

I generally don't like np.append, since it is often misused, especially in loops. For this it's ok, but I think column_stack is cleaner.

===

In [254]: list(zip(*[iter(vector)]*2+[iter(inserted_elements)]))                                         
Out[254]: [(1, 2, 2), (3, 4, 2), (5, 6, 2), (7, 8, 2), (9, 10, 2)]



回答5:


I don't think there's an easy NumPy way to do this for any possible size of arrays, but here's a python way of doing so using iterators and list comprehension:

it1, it2 = map(iter, (vector, inserted_elements))
n = sum(map(len, (vector, inserted_elements)))

[next(it2) if i % 3 == 0 else next(it1) for i in range(1, n+1)]
# [1, 2, 2, 3, 4, 2, 5, 6, 2, 7, 8, 2, 9, 10, 2]

Every 3rd element in the output will come from it2, the iterator for inserted_elements. The rest come from it1 which corresponds to vector.



来源:https://stackoverflow.com/questions/56286403/insert-items-from-list-to-another-list-every-n-positions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!