简体   繁体   English

每 n 个位置将列表中的项目插入到另一个列表

[英]Insert items from list to another list every n positions

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.不仅 Python 列表而且使用 numpy 数组的答案也很好。

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:我不认为有一种简单的 NumPy 方法可以对任何可能大小的数组执行此操作,但这里有一种使用迭代器和列表理解来执行此操作的 Python 方法:

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 3 rd element in the output will come from it2 , the iterator for inserted_elements .在输出的每个第三元素将来自it2 ,对于迭代器inserted_elements The rest come from it1 which corresponds to vector .其余的来自it1对应于vector

numpy array step: numpy 数组步骤:

1. 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. 2.

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

3. 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. 4.

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

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传统的for循环的做法可能会像下面这样,当你随意从2元vector ,并从1元inserted_elements ,使output列表

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]

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.它使用“惯用语”来获取大小为 n 组的项目, [iter(alist)]*nitertools.chain作为展平嵌套列表的一种方式。

A deleted answer used np.insert .已删除的答案使用np.insert For this I believe insert uses masking as demonstrated below:为此,我相信insert使用掩码,如下所示:

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.append答案的一个变体是:

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.我通常不喜欢np.append ,因为它经常被滥用,尤其是在循环中。 For this it's ok, but I think column_stack is cleaner.为此,没关系,但我认为column_stack更干净。

=== ===

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)]

Here's an itertools based approach, which also works for an arbitrary number of elements to be inserted from one list to the other.这是一种基于itertools的方法,它也适用于从一个列表插入到另一个列表的任意数量的元素。 For this I've defined a generator function, which will insert and element from l2 into l1 every i items:为此,我定义了一个生成器函数,它将把l2元素插入到l1i项目:

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 .这是通过使用itertools.islice在每次迭代中从迭代器l1产生最多i项目来实现的。 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 ).使用yield from我们产生的项目与切片可迭代中的项目一样多,因此可迭代运行到耗尽,( for v in g: yield v的快捷方式for v in g: yield v )。

Finally we can wrap the yield statements with a try / expect to catch the StopIteration warning.最后,我们可以用try / expect来包装yield语句以捕获StopIteration警告。


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:如果我们想每 3 个项目添加一个l2项目:

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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM