在 Python 中交错多个相同长度的列表[重复]
- 2024-12-24 08:55:00
- admin 原创
- 80
问题描述:
在 Python 中,有没有一种好的方法可以交错两个相同长度的列表?
假设我得到[1,2,3]
和[10,20,30]
。我想将它们转换为[1,10,2,20,3,30]
。
解决方案 1:
发布问题后,我意识到我可以简单地执行以下操作:
[val for pair in zip(l1, l2) for val in pair]
其中l1
和l2
是两个列表。
如果有 N 个列表需要交错,那么
lists = [l1, l2, ...]
[val for tup in zip(*lists) for val in tup]
解决方案 2:
对于 Python>=2.3,有扩展的切片语法:
>>> a = [0, 2, 4, 6, 8]
>>> b = [1, 3, 5, 7, 9]
>>> c = a + b
>>> c[::2] = a
>>> c[1::2] = b
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
该行c = a + b
是创建长度恰到好处的新列表的简单方法(在此阶段,其内容并不重要)。接下来的两行执行交错a
和的实际工作b
:第一行将的元素分配a
给的所有偶数索引c
;第二行将的元素分配b
给的所有奇数索引c
。
解决方案 3:
鉴于
a = [1, 2, 3]
b = [10, 20, 30]
c = [100, 200, 300, 999]
代码
假设列表长度相等,则可以得到一个带有 和itertools.chain
的交错列表zip
:
import itertools
list(itertools.chain(*zip(a, b)))
# [1, 10, 2, 20, 3, 30]
替代方案
itertools.zip_longest
更一般地,对于不平等的列表,使用zip_longest
(推荐):
[x for x in itertools.chain(*itertools.zip_longest(a, c)) if x is not None]
# [1, 100, 2, 200, 3, 300, 999]
许多列表可以安全地交错:
[x for x in itertools.chain(*itertools.zip_longest(a, b, c)) if x is not None]
# [1, 10, 100, 2, 20, 200, 3, 30, 300, 999]
more_itertools
+
随 itertools 配方一起提供的库roundrobin
,interleave
以及interleave_longest
。
import more_itertools
list(more_itertools.roundrobin(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave_longest(a, c))
# [1, 100, 2, 200, 3, 300, 999]
yield from
最后,关于 Python 3 的一些有趣的事情(虽然不推荐):
list(filter(None, ((yield from x) for x in zip(a, b))))
# [1, 10, 2, 20, 3, 30]
list([(yield from x) for x in zip(a, b)])
# [1, 10, 2, 20, 3, 30]
+使用安装pip install more_itertools
解决方案 4:
我需要一种方法来使用不同大小的列表来完成此操作,但接受的答案并未解决这个问题。
我的解决方案使用了一个生成器,因此它的使用看起来更好一些:
def interleave(l1, l2):
iter1 = iter(l1)
iter2 = iter(l2)
while True:
try:
if iter1 is not None:
yield next(iter1)
except StopIteration:
iter1 = None
try:
if iter2 is not None:
yield next(iter2)
except StopIteration:
iter2 = None
if iter1 is None and iter2 is None:
raise StopIteration()
用法如下:
>>> a = [1, 2, 3, 4, 5]
>>> b = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list(interleave(a, b))
[1, 'a', 2, 'b', 3, 'c', 4, 'd', 5, 'e', 'f', 'g']
>>> list(interleave(b, a))
['a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 5, 'f', 'g']
解决方案 5:
选择:
>>> l1=[1,2,3]
>>> l2=[10,20,30]
>>> [y for x in map(None,l1,l2) for y in x if y is not None]
[1, 10, 2, 20, 3, 30]
这是因为map可以并行处理列表。它在 2.2 下的工作方式相同。它本身(作为None
调用函数)map
生成一个元组列表:
>>> map(None,l1,l2,'abcd')
[(1, 10, 'a'), (2, 20, 'b'), (3, 30, 'c'), (None, None, 'd')]
然后只需展平元组列表。
当然,优点是map
可以适用于任意数量的列表,即使它们的长度不同也可以工作:
>>> l1=[1,2,3]
>>> l2=[10,20,30]
>>> l3=[101,102,103,104]
>>> [y for x in map(None,l1,l2,l3) for y in x if y in not None]
[1, 10, 101, 2, 20, 102, 3, 30, 103, 104]
解决方案 6:
这也是一种方法:
list1 = [1, 2, 3]
list2 = [10, 20, 30]
list(sum(zip(list1, list2), ()))
想法是类似的。
将列表压缩在一起。(使用 zip)
展平为元组(使用 sum(..., ())
转换为列表
解决方案 7:
我最喜欢 aix 的解决方案。这是我认为在 2.2 中应该起作用的另一种方法:
>>> x=range(3)
>>> x
[0, 1, 2]
>>> y=range(7,10)
>>> y
[7, 8, 9]
>>> sum(zip(x,y),[])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "tuple") to list
>>> sum(map(list,zip(x,y)),[])
[0, 7, 1, 8, 2, 9]
还有一种方法:
>>> a=[x,y]
>>> [a[i][j] for j in range(3) for i in (0,1)]
[0, 7, 1, 8, 2, 9]
和:
>>> sum((list(i) for i in zip(x,y)),[])
[0, 7, 1, 8, 2, 9]
解决方案 8:
一种有趣的方法是使用heapq.merge
最终列表中的位置作为关键:
from heapq import merge
from itertools import count
a = [1,2,3]
b = [10,20,30]
counter = count()
res = list(merge(a, b, key=lambda x: next(counter)))
print(res)
输出
[1, 10, 2, 20, 3, 30]
对于多个列表,你可以直接解压它们:
from heapq import merge
from itertools import count
a = [1, 2, 3]
b = [10, 20, 30]
c = [11, 21, 31]
counter = count()
res = list(merge(*[a, b, c], key=lambda x: next(counter)))
print(res)
输出
[1, 10, 11, 2, 20, 21, 3, 30, 31]
解决方案 9:
[el for el in itertools.chain(*itertools.izip_longest([1,2,3], [4,5])) if el is not None]
只要你没有None
你想保留的东西
解决方案 10:
为了回答问题标题“在 Python 中交错多个长度相同的列表”,我们可以概括 @ekhumoro 的 2 列表答案。这明确要求列表长度相同,这与 @NPE 的(优雅)解决方案不同
import itertools
def interleave(lists):
"""Interleave a list of lists.
:param lists: List of lists; each inner length must be the same length.
:returns: interleaved single list
:rtype: list
"""
if len(set(len(_) for _ in lists)) > 1:
raise ValueError("Lists are not all the same length!")
joint = list(itertools.chain(*lists))
for l_idx, li in enumerate(lists):
joint[l_idx::len(lists)] = li
return joint
例子:
>>> interleave([[0,2,4], [1, 3, 5]])
[0, 1, 2, 3, 4, 5]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12]])
[0, 1, 10, 2, 3, 11, 4, 5, 12]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14, 15]])
[0, 1, 10, 13, 2, 3, 11, 14, 4, 5, 12, 15]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 10, in interleave
ValueError: Lists are not all the same length!
>>> interleave([[0,2,4]])
[0, 2, 4]
解决方案 11:
参加聚会已经太晚了,并且有很多好的答案,但我还想使用extend()
方法提供一个简单的解决方案:
list1 = [1, 2, 3]
list2 = [10, 20, 30]
new_list = []
for i in range(len(list1)):
new_list.extend([list1[i], list2[i]])
print(new_list)
输出:
[1, 10, 2, 20, 3, 30]
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)