如何以特定间隔将列表插入列表?

How can I insert a list into a list at certain intervals?

我有 2 个列表,我想以 7 的间隔将一个列表添加到另一个列表中。

在我的 iPython 'whos' 中,我有:

Variable                      Type             Data/Info
full_links                    list             n=15
spannedcopynotags             list             n=105

所以,我想在 'spannedcopynotags' 中的每第 7 个索引项之后添加一个 'full_links' 中的索引项。

'full_links'是15个http://link,'spannedcopynotags'是所有link的描述信息。因此,link 的其他顺序与描述不符。

您可以使用 list.insert() 来达到这个目的,例如:

list1 = range(100)
list2 = range(10)

pos = 0
for item in list2:
    list1.insert(pos, item)
    pos += 7

请注意,如果位置超过列表的长度,list.insert() 会将项目插入到列表的末尾。

另一个解决方案是每 step (7) 个元素添加一个 full_links 元素 full_links.

# data for testing
spannedcopynotags = range(105)
full_links = ['%c' % c for c in range(65, 65+15)]

# compute step
length = len(spannedcopynotags)
step = length/len(full_links)

# main part
result = []
for pos_links, pos_spanned in enumerate(range(0, length, step)):
    result+= spannedcopynotags[pos_spanned:pos_spanned+step] + [full_links[pos_links]]

# main part in an unreadable one-liner
result = [
    item
    for pos, link in zip(range(0, length, step), full_links)
    for item in (spannedcopynotags[pos:pos+step] + [link])
]

预期结果:

[0, 1, 2, 3, 4, 5, 6, 'A', 7, 8, 9, 10, 11, 12, 13, 'B', 14, ...]

我同意 for 循环是最简单、最容易理解的方法。使用 zip 有一些优点,但是:

  • 它不修改输入列表
  • 更容易正确处理列表长度的重要差异

下面是在这种情况下如何使用 zip 的示例:

x = list('abcdefghijklmnopqrstu')
y = list('123')
it_x = iter(x)
result = [
    item for items in zip(it_x, it_x, it_x, it_x, it_x, it_x, y) 
    for item in items
]

要了解其工作原理,请考虑:

zip(x, x, x, x, x, x, x, y)

相当于:

zip(iter(x), iter(x), iter(x), iter(x), iter(x), iter(x), iter(x), y)

通过自己创建迭代器,并使用相同的迭代器 7 次而不是独立的迭代器,您总是会得到下一个项目,而不是相同的项目 7 次。

要缩短一点,您可以使用参数解包:

composition = 7*[iter(x)] + [y]
result = [item for items in zip(*composition] for item in items]

如果您不喜欢双重列表理解:

from itertools import chain
result = list(chain.from_iterable(zip(*composition)))

严格来说,所有这些都依赖于 zip 的实现细节,即按顺序获取其参数中的项目,但它有效并且不太可能改变。 文档上写着这个依赖的求值顺序是有保证的