如何以特定间隔将列表插入列表?
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
的实现细节,即按顺序获取其参数中的项目,但它有效并且不太可能改变。 文档上写着这个依赖的求值顺序是有保证的
我有 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
的实现细节,即按顺序获取其参数中的项目,但它有效并且不太可能改变。