如何在序列中添加第n个?

时间:2019-03-05 00:39:26

标签: python

如果我有一个列表:

["a1", "b1", "c1", "a2", "b2", "c2", "a3", "b3", "c3"]

,我想创建一个新列表,例如:

["a1", "a2", "a3", "b1", "b2", "b3", "c1", "c2", "c3"]

我正在尝试在for循环中执行此操作,以便依次添加到新列表:

newlist = []
for i in oldlist:
    newlist.append(oldlist[i])
    newlist.append(oldlist[2*i])
    newlist.append(oldlist[3*i])
    i+3

我的代码的问题在于,它将一口气地附加所有ii*3的值,而不是让我的每个第n版都有机会。 / p>

3 个答案:

答案 0 :(得分:5)

您可以跨步使用所需的偏移量序列,可以使用itertools展平到一维列表中。

>>> import itertools
>>> d =  ['a1', 'b1', 'c1', 'a2', 'b2', 'c2', 'a3', 'b3', 'c3']
>>> list(itertools.chain.from_iterable([d[::3], d[1::3], d[2::3]]))
['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3']

您还可以使用numpy通过对数组进行重塑,转置然后再次展平来进行类似的操作

>>> import numpy as np
>>> d =  np.array(['a1', 'b1', 'c1', 'a2', 'b2', 'c2', 'a3', 'b3', 'c3'])
>>> np.reshape(d, (d.size//3, 3)).T.flatten()
array(['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3'], dtype='<U2')

答案 1 :(得分:2)

假设您希望间隔为n = 3

>>> a=[1,2,3,11,22,33,111,222,333]
>>> res=[]
>>> n=3
>>> for i in range(0,n):
...     for z in a[i::n]:
...         res.append(z)
... 
>>> 
>>> res
[1, 11, 111, 2, 22, 222, 3, 33, 333]

更多pythonic

>>> a=['a1', 'b1', 'c1', 'a2', 'b2', 'c2', 'a3', 'b3', 'c3']
>>> res = [val for i in range(3) for val in a[i::3]]
>>> res
['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3']

其中a[i::3]仅以3的步长从ith索引开始遍历列表。

答案 2 :(得分:0)

zip的一个有趣的功能是可以将输入分组为固定长度的组,而无需显式切片。 The grouper recipe使您可以转换为固定长度的组,然后可以将其解压缩以进行另一轮zip的打包,以便将每个组的前几个元素配对:

>>> lst = ["a1", "b1", "c1", "a2", "b2", "c2", "a3", "b3", "c3", 'a4', 'b4', 'c4']  # Added three more elements so it's clear it's three groups of four, three of three being harder to see
>>> list(zip(*[iter(lst)]*3))  # Grouped sequentially so a is first element of each group
[('a1', 'b1', 'c1'),
 ('a2', 'b2', 'c2'),
 ('a3', 'b3', 'c3'),
 ('a4', 'b4', 'c4')]

>>> list(zip(*zip(*[iter(lst)]*3))) # Unpack and zip again to group a's with a's, b's with b's, etc.
[('a1', 'a2', 'a3', 'a4'), ('b1', 'b2', 'b3', 'b4'), ('c1', 'c2', 'c3', 'c4')]

>>> from itertools import chain
>>> list(chain.from_iterable(zip(*zip(*[iter(lst)]*3))))  # Flatten out to single list
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']

您可以通过以下方式获得相同的结果:

>>> list(chain.from_iterable(lst[i::3] for i in range(3)))
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']

multi-zip只是将所有工作推到内置函数中(根本没有Python级别的循环)。再加上后者要长两个完整字符,似乎与CoryKramer的答案太相似。 :-)就是说,如果您输入的内容长度不均匀,则后者更为优越;当最短的可迭代数用尽时,zip停止迭代,而itertools.zip_longest必须使用填充值。实际切片和展平可避免该问题。