混合类型列表阈值聚类:寻求itertools.groupby等进阶实现方案
问题描述
现有一个包含str、int和float类型元素的列表,需求为:当遇到大于阈值(此处阈值为3)的数值元素时,将该元素之前的所有元素聚类为子列表。已实现基础循环版代码及预期输出如下:
L = ["this is", "my", 1, "first line", 4, "however this", 3.5, "is my last line", 4] out = [] temp = [] for x in L: if isinstance(x, str) or x <3: temp.append(x) else: out.append(temp) temp = [] print(out) # 输出:[['this is', 'my', 1, 'first line'], ['however this'], ['is my last line']]
现希望了解如何使用itertools.groupby、filter或其他进阶方法实现该聚类逻辑。
解决方案
方法一:使用itertools.groupby
groupby的核心是基于分组键聚合元素,我们可以通过标记分组ID的方式,把分割点前后的元素分到不同组,同时排除分割元素本身:
from itertools import groupby L = ["this is", "my", 1, "first line", 4, "however this", 3.5, "is my last line", 4] threshold = 3 group_id = 0 markers = [] for x in L: if isinstance(x, (int, float)) and x > threshold: markers.append(None) # 分割元素标记为None,不归属任何组 group_id += 1 else: markers.append(group_id) # 配对元素与标记,过滤分割点后按分组ID聚合 paired = [(m, x) for m, x in zip(markers, L) if m is not None] result = [list(g) for _, g in groupby(paired, key=lambda item: item[0])] print(result) # 输出:[['this is', 'my', 1, 'first line'], ['however this'], ['is my last line']]
方法二:使用生成器函数
用生成器封装聚类逻辑,遍历列表时收集元素,遇到分割条件就输出当前子列表,代码更简洁且符合迭代器风格:
L = ["this is", "my", 1, "first line", 4, "however this", 3.5, "is my last line", 4] threshold = 3 def cluster_list(lst, threshold): temp = [] for x in lst: if isinstance(x, (int, float)) and x > threshold: yield temp temp = [] else: temp.append(x) result = list(cluster_list(L, threshold)) print(result) # 输出:[['this is', 'my', 1, 'first line'], ['however this'], ['is my last line']]
方法三:结合itertools.takewhile和itertools.dropwhile
通过这两个函数交替截取剩余列表,逐步提取符合条件的子列表:
from itertools import takewhile, dropwhile L = ["this is", "my", 1, "first line", 4, "however this", 3.5, "is my last line", 4] threshold = 3 def should_include(x): return isinstance(x, str) or x < threshold result = [] remaining = L while remaining: # 提取当前子列表:所有符合条件的元素直到第一个分割元素 sublist = list(takewhile(should_include, remaining)) if sublist: result.append(sublist) # 跳过当前子列表和后续的分割元素 remaining = dropwhile(should_include, remaining) if remaining: remaining = remaining[1:] print(result) # 输出:[['this is', 'my', 1, 'first line'], ['however this'], ['is my last line']]
内容的提问来源于stack exchange,提问作者Bharat Sharma
相关产品推荐
相关产品推荐

