繁体   English   中英

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

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

我有以下清单。

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

我想通过插入每两个元素来获得以下内容。

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

不仅 Python 列表而且使用 numpy 数组的答案也很好。

我不认为有一种简单的 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]

在输出的每个第三元素将来自it2 ,对于迭代器inserted_elements 其余的来自it1对应于vector

numpy 数组步骤:

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

传统的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)

列表理解中的相同内容将是

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

输出将是

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

这是一种有点晦涩的方法 - 但它比其他任何方法都快(到目前为止):

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

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

已删除的答案使用np.insert 为此,我相信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

np.append答案的一个变体是:

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

我通常不喜欢np.append ,因为它经常被滥用,尤其是在循环中。 为此,没关系,但我认为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)]

这是一种基于itertools的方法,它也适用于从一个列表插入到另一个列表的任意数量的元素。 为此,我定义了一个生成器函数,它将把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

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

最后,我们可以用try / expect来包装yield语句以捕获StopIteration警告。


让我们尝试使用建议的示例:

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]

如果我们想每 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