使用itertools根据值的变化拆分列表

问题描述 投票:2回答:4

我有一个列表,我试图通过改变值来分组:

input_list = ["I", "Non-I", "Non-I", "Non-I", "I", "Non-I", "Non-I", "Non-I"]

我需要的是一个输出列表,用于分隔以“I”开头的每个组:

output_list = [["I", "Non-I", "Non-I", "Non-I"], ["I", "Non-I", "Non-I", "Non-I"]]

我尝试过以下方法:

#!/usr/bin/env python3

from itertools import groupby

input_list = ["I", "Non-I", "Non-I", "Non-I", "I", "Non-I", "Non-I", "Non-I"]

output_list = [["I", "Non-I", "Non-I", "Non-I"], ["I", "Non-I", "Non-I", "Non-I"]]

for key, val in groupby(input_list, lambda x: x == "I"):
    print(list(val))

......它几乎返回我想要的东西:

['I']
['Non-I', 'Non-I', 'Non-I']
['I']
['Non-I', 'Non-I', 'Non-I']

现在我可以继续合并,即合并所有其他元素,但这似乎是一个黑客。我还提出了迭代的“经典”方式:

ret = []
curr_list = []
for element in input_list:
    if element != "I":
        curr_list.append(element)
    if element == "I":
        if curr_list:
            ret.append(curr_list)
        curr_list = [element]
ret.append(curr_list)

是否有更多的Pythonic方式来实现我的需求?

python itertools
4个回答
1
投票

您可以使groupby的输出成为生成器表达式,并通过将其自身压缩来配对输出:

from itertools import groupby
groups = (list(g) for _, g in groupby(input_list, 'I'.__eq__))
print([[i for l in pair for i in l] for pair in zip(groups, groups)])

这输出:

[['I', 'Non-I', 'Non-I', 'Non-I'], ['I', 'Non-I', 'Non-I', 'Non-I']]

1
投票

一种方法是找到一个字符串以"I"开头的索引,并使用itertools.islice使用这些索引对列表进行切片:

from itertools import islice

ix = [ix for ix,i in enumerate(input_list) if i[0]=='I'] + [len(input_list)]
input_ = iter(input_list)
[list(islice(input_, i)) for i in ix[1:]]

产量

[['I', 'Non-I', 'Non-I', 'Non-I'], ['I', 'Non-I', 'Non-I', 'Non-I']]

1
投票

您可以使用索引来存储I的第一个实例,其中包含以下非I值:

import itertools
input_list = ["I", "Non-I", "Non-I", "Non-I", "I", "Non-I", "Non-I", "Non-I"]
d = [list(b) for _, b in itertools.groupby(input_list, key=lambda x:x == 'I')]
final_result = [[*d[i], *d[i+1]] for i in range(0, len(d), 2)]

输出:

[['I', 'Non-I', 'Non-I', 'Non-I'], ['I', 'Non-I', 'Non-I', 'Non-I']]

1
投票

还要查找“I”的索引:s,然后通过切片input_list为每个块创建一个单独的列表。

location_list = [i for i, x in enumerate(input_list) if x == "I"]
[input_list[i:j] for i,j in zip(location_list, location_list[1:]+[len(input_list)])]

随着输出:

[['I', 'Non-I', 'Non-I', 'Non-I'], ['I', 'Non-I', 'Non-I', 'Non-I']]

如果您无法使用itertools,则尝试不使用任何导入。

© www.soinside.com 2019 - 2024. All rights reserved.