遍历不同长度列表中的所有列表
Iterate over all lists inside a list of varied lengths
我有一个列表列表。它看起来像这样:
[
[4,7,9,10],
[5,14,55,24,121,56, 89,456, 678],
[100, 23, 443, 34, 1243,]
....
]
我想进行迭代,以便在每次迭代时从所有列表中获取该索引的相应元素,如果列表为空,则将其删除。
例如,当索引为 0 时,我想要一个列表,该列表将从列表 1 的列表 0,5 扩展(添加)4,从列表 2(所有列表的第 0 个索引)扩展(添加)100,如果列表得到空(如列表 0 将在第 3 次迭代后被完全覆盖,跳过它。因此迭代应跳过此列表并移动到下一个列表。
所以输出应该是这样的:[4,5,100, 7, 14, 23, 9, 55, 443, 10, 24, 34, 121, 1243, 56. 89, 456, 678]
我想要一个扩展这些值的列表。
您可以使用 itertools.zip_longest()
(它是标准库的一部分,是内置 zip()
的替代方法,它将其输出截断为最短的参数),以 reorder/rotate 列表,然后使用双列表理解来展平该输出。
from itertools import zip_longest
inp = [
[4,7,9,10],
[5,14,55,24,121,56, 89,456, 678],
[100, 23, 443, 34, 1243,]
]
output = [
elem
for tup in zip_longest(*inp) # if we don't provide a fillvalue...
for elem in tup # ...missing elements are replaced with None...
if elem is not None # ...which we can filter out
]
# [4, 5, 100, 7, 14, 23, 9, 55, 443, 10, 24, 34, 121, 1243, 56, 89, 456, 678]
zip_longest
是有问题的,因为如果它出现在输入中,任何解决方案都会默默地删除 fillvalue
(这可以解决,但它总是会有点 hacky)。
最通用的解决方案是来自 the itertools
module 的 roundrobin
配方:
from itertools import cycle, islice
def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
# Recipe credited to George Sakkis
num_active = len(iterables)
nexts = cycle(iter(it).__next__ for it in iterables)
while num_active:
try:
for next in nexts:
yield next()
except StopIteration:
# Remove the iterator we just exhausted from the cycle.
num_active -= 1
nexts = cycle(islice(nexts, num_active))
对于您的输入,您可以执行以下操作:
mylist = [
[4,7,9,10],
[5,14,55,24,121,56, 89,456, 678],
[100, 23, 443, 34, 1243,]
....
]
print(list(roundrobin(*mylist)))
一件简单的事情就是通过附加已知值将给定列表转换为大小相等的列表。然后我们可以迭代它并仅在元素不是已知值时添加到结果。
res = []
extra_val = '#'
max_len = float('-inf')
for each in l:
max_len = max(max_len, len(each))
for each in l:
if len(each) < max_len:
n = max_len - len(each)
extra_list = [extra_val]*n
each.extend(extra_list)
for i in range(max_len):
for j in range(len(l)):
if l[j][i] != extra_val:
res.append(l[j][i])
print(res)
我有一个列表列表。它看起来像这样:
[
[4,7,9,10],
[5,14,55,24,121,56, 89,456, 678],
[100, 23, 443, 34, 1243,]
....
]
我想进行迭代,以便在每次迭代时从所有列表中获取该索引的相应元素,如果列表为空,则将其删除。
例如,当索引为 0 时,我想要一个列表,该列表将从列表 1 的列表 0,5 扩展(添加)4,从列表 2(所有列表的第 0 个索引)扩展(添加)100,如果列表得到空(如列表 0 将在第 3 次迭代后被完全覆盖,跳过它。因此迭代应跳过此列表并移动到下一个列表。
所以输出应该是这样的:[4,5,100, 7, 14, 23, 9, 55, 443, 10, 24, 34, 121, 1243, 56. 89, 456, 678]
我想要一个扩展这些值的列表。
您可以使用 itertools.zip_longest()
(它是标准库的一部分,是内置 zip()
的替代方法,它将其输出截断为最短的参数),以 reorder/rotate 列表,然后使用双列表理解来展平该输出。
from itertools import zip_longest
inp = [
[4,7,9,10],
[5,14,55,24,121,56, 89,456, 678],
[100, 23, 443, 34, 1243,]
]
output = [
elem
for tup in zip_longest(*inp) # if we don't provide a fillvalue...
for elem in tup # ...missing elements are replaced with None...
if elem is not None # ...which we can filter out
]
# [4, 5, 100, 7, 14, 23, 9, 55, 443, 10, 24, 34, 121, 1243, 56, 89, 456, 678]
zip_longest
是有问题的,因为如果它出现在输入中,任何解决方案都会默默地删除 fillvalue
(这可以解决,但它总是会有点 hacky)。
最通用的解决方案是来自 the itertools
module 的 roundrobin
配方:
from itertools import cycle, islice
def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
# Recipe credited to George Sakkis
num_active = len(iterables)
nexts = cycle(iter(it).__next__ for it in iterables)
while num_active:
try:
for next in nexts:
yield next()
except StopIteration:
# Remove the iterator we just exhausted from the cycle.
num_active -= 1
nexts = cycle(islice(nexts, num_active))
对于您的输入,您可以执行以下操作:
mylist = [
[4,7,9,10],
[5,14,55,24,121,56, 89,456, 678],
[100, 23, 443, 34, 1243,]
....
]
print(list(roundrobin(*mylist)))
一件简单的事情就是通过附加已知值将给定列表转换为大小相等的列表。然后我们可以迭代它并仅在元素不是已知值时添加到结果。
res = []
extra_val = '#'
max_len = float('-inf')
for each in l:
max_len = max(max_len, len(each))
for each in l:
if len(each) < max_len:
n = max_len - len(each)
extra_list = [extra_val]*n
each.extend(extra_list)
for i in range(max_len):
for j in range(len(l)):
if l[j][i] != extra_val:
res.append(l[j][i])
print(res)