我想把一个嵌套列表(其中的列表有不同的长度(组合成一个。我想先按索引添加。然后按大小排序。
示例:
lsts = [
[7, 23, 5, 2],
[3, 8, 1],
[99, 23, 9, 23, 74]
]
merged = [3, 7, 99, 8, 23, 23, 1, 5, 9, 2, 23, 74]
我想在不导入的情况下解决这个问题。
假设您的列表列表不能包含None
S,则可以使用itertools.zip_longest
:执行此操作
from itertools import zip_longest
result = []
for row in zip_longest(*lsts):
row = (x for x in row if x is not None)
for x in sorted(row):
result.append(x)
print(result)
这里有一行代码:
import functools
import itertools
functools.reduce(lambda x,y: x+y, [sorted(x for x in p if x is not None) for p in itertools.zip_longest(*lsts)])
输出:
[3, 7, 99, 8, 23, 23, 1, 5, 9, 2, 23, 74]
我将在上一步的结果基础上逐步解释每个构建的解决方案。
要按索引对每个列表中的项目进行分组,itertools.zip_lengest((就是这样做的工具:
>>> import itertools as it
>>> MISSING = object() # a sentinel
>>> lsts = [
[7, 23, 5, 2],
[3, 8, 1],
[99, 23, 9, 23, 74]
]
>>> it.zip_longest(*lsts, fillvalue=MISSING)
>>> list(_)
[(7, 3, 99), (23, 8, 23), (5, 1, 9), (2, <object object at 0x7f529e9b4260>, 23), (<object object at 0x7f529e9b4260>, <object object at 0x7f529e9b4260>, 74)]
这会在需要的地方使用MISSING填充值将列表元素分组为n元组,因为列表的长度可能不相等。
下一步是对每个n元组进行迭代,并在内部对其进行排序(同时跳过MISSING值(。内置函数sorted((在这里很方便:
>>> list(
sorted(x for x in ntuple if x is not MISSING)
for ntuple in it.zip_longest(*lsts, fillvalue=MISSING)
)
[[3, 7, 99], [8, 23, 23], [1, 5, 9], [2, 23], [74]]
最后一步是压平这个列表序列,我们将使用itertools.chain,from_interable((:
>>> list(it.chain.from_iterable(
sorted(x for x in ntuple if x is not MISSING)
for ntuple in it.zip_longest(*lsts, fillvalue=MISSING)
))
[3, 7, 99, 8, 23, 23, 1, 5, 9, 2, 23, 74]
chain.from_iterable()
的好处在于,它不会重复地将较小的列表连接到越来越长的最终列表中,从而提高了效率。它也在C级AFAIK上做到了这一点。
值得注意的是,None
也可以用来代替MISSING
sentinel,但我使用了MISSING来演示fillvalue
是如何工作的(例如,如果你愿意,你可能想使用零或其他东西(。
zip_lengest完成了这项工作。剩下的是清理/格式化
In [1]: from itertools import zip_longest, chain
In [2]: lsts = [
...: [7, 23, 5, 2],
...: [3, 8, 1],
...: [99, 23, 9, 23, 74]
...: ]
In [3]: [v for v in chain.from_iterable(zip_longest(*lsts)) if v !=None]
Out[3]: [7, 3, 99, 23, 8, 23, 5, 1, 9, 2, 23, 74]