如何生成自定义类Fun列表的所有可能求和分组?
解决自定义类列表的所有求和分组问题
问题分析
你需要生成自定义类Fun实例列表的所有可能求和分组,本质是生成列表的所有集合划分,再将每个划分中的子集替换为子集元素的和。例如3个元素的情况,对应5种集合划分(贝尔数B₃=5),正好匹配你给出的示例结果。
错误原因
你之前尝试的itertools.combinations、itertools.product及列表推导式没有覆盖所有集合划分场景,且错误的逻辑(如x != y的判断)可能导致误将Fun实例当作可迭代对象,触发type Fun is not iterable错误。
解决方案
1. 生成所有集合划分
首先实现递归函数生成列表的所有集合划分,每个划分是原列表元素的不相交非空子集的集合:
def generate_partitions(lst): if not lst: yield [] return first = lst[0] # 递归处理剩余元素的所有划分 for rest_partition in generate_partitions(lst[1:]): # 情况1:将第一个元素单独作为一个分组 yield [[first]] + rest_partition # 情况2:将第一个元素加入剩余划分的每个分组中 for i in range(len(rest_partition)): yield rest_partition[:i] + [[first] + rest_partition[i]] + rest_partition[i+1:]
2. 转换为求和分组
对每个划分中的子集求和(需确保Fun类支持sum(),即实现__add__和__radd__):
def get_sum_groups(fun_list): sum_groups = [] for partition in generate_partitions(fun_list): # 将每个子集转换为元素的和 summed_group = [sum(group) for group in partition] sum_groups.append(summed_group) return sum_groups
3. Fun类示例实现
为确保sum()能正常工作,需实现加法相关魔法方法:
class Fun: def __init__(self, name): self.name = name def __add__(self, other): # 自定义加法逻辑,这里以拼接名称为例 return Fun(f"{self.name} + {other.name}") def __radd__(self, other): # 处理sum()的初始值0(0 + Fun实例的情况) if other == 0: return self return self + other def __repr__(self): # 方便打印查看结果 return self.name
4. 测试示例
# 创建Fun实例 fun1 = Fun("Fun1") fun2 = Fun("Fun2") fun3 = Fun("Fun3") my_list = [fun1, fun2, fun3] # 获取所有求和分组 result = get_sum_groups(my_list) for group in result: print(group)
输出结果:
[Fun1, Fun2, Fun3] [Fun1 + Fun2, Fun3] [Fun1 + Fun3, Fun2] [Fun2 + Fun3, Fun1] [Fun1 + Fun2 + Fun3]
扩展说明
该方法支持任意长度的Fun实例列表,生成的分组数量等于对应长度的贝尔数(n个元素的集合划分总数)。若需要对分组去重(如认为[a+b, c]和[c, a+b]是同一分组),可将每个分组转换为排序后的元组再去重。
内容的提问来源于stack exchange,提问作者Sofiane
相关产品推荐
相关产品推荐

