[英]Union sets of lists/sets in Python
我正在编写一个用于查找数字S列表的所有子集的小函数,输出是列表的列表。
def subsets(S):
if S is None or len(S) == 0:
return [[]]
output_list = []
sub = [[[], [S[0]]]]
for i in xrange(1, len(S)):
without_ith = sub[i - 1]
with_ith = [element + [S[i]] for element in without_ith]
# convert to set of tuples, for set union
without_set = set(tuple(element) for element in without_ith)
with_set = set(tuple(element) for element in with_ith)
new_set = without_set | with_set
# convert back to list of lists
new = list(list(element) for element in new_set)
sub.append(new)
# sort each sublist into non-descending order
# output_list = [sorted(element) for element in sub[-1]]
for element in sub[-1]:
output_list.append(sorted(element))
return output_list
该算法在帖子的可接受答案中有所描述: 查找集合的所有子集
令我烦恼的是从列表列表到元组集的转换,然后执行两组元组的并集,然后再转换回列表列表。 所有这些都在每次迭代中发生。 原因是在Python中,集合必须包含不可哈希对象,这些对象是可哈希的,以便与其他集合执行集合操作。 但是列表和集合是可变且不可散列的,因此需要元组或Frozensets作为此类集合的元素。 对于我的代码,我首先对元素列表进行了变异,然后将它们转换为联合的元组,然后再转换回列表。 我想知道是否有解决方法吗? 它看起来不是很干净和高效。
(还有一个小小的疑问是列表# output_list = [sorted(element) for element in sub[-1]]
我注释掉了# output_list = [sorted(element) for element in sub[-1]]
。我使用的是PyCharm,它建议将列表解析替换为for循环。是什么原因?我认为列表理解总是更好。
我喜欢“计数”方法来执行诸如“返回所有子集”之类的任务。 假设S
是一个没有重复的数字列表:
def subsets(S): # S is a list of `whatever`
result = []
S = sorted(S) # iff S can't be assumed to be sorted to start
# S = sorted(set(S)) if duplicates are possible and must be pruned
for i in range(2**len(S)):
asubset = []
for j, x in enumerate(S):
if i & 1<<j: asubset.append(x)
result.append(asubset)
return result
本质上,这利用了N个事物的子集与从0到2**N - 1
的整数的二进制形式之间的1-1对应关系。
有你之间没有重复项目的without_ith
和with_ith
列表,因为前者的名单不会包含S[i]
和那些在后者总是这样。 这意味着当您将它们组合在一起时,无需使用set
对象,只需将一个列表连接到另一个列表上,便会很好! 或者,您可以使用单个列表变量,并通过列表理解extend
它:
def subsets(S):
results = [[]]
for x in S:
results.extend([item + [x] for item in results])
return results
如果您的输入列表已排序,则所有子集也将都是。 如果输入不一定总是顺序正确的,而您需要输出是正确的,则在sorted(S)
而不是S
上循环。 子集中的项目将始终以其迭代的顺序出现。
请注意,在extend
调用中使用列表推导,而不是生成器表达式,这一点很重要。 生成器将继续迭代新添加的项,从而导致无限循环(直到系统用尽内存来扩展列表)。
看起来列表理解比附加项目要快,因为使用列表不需要将列表附加功能加载到内存中。 在深层列表理解与附加比较中查看这篇出色的文章 。
因此,对于您的特定问题,我想列表理解会更快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.