[英]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)]*n
和itertools.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
元素插入到l1
每i
项目:
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.