【发布时间】:2017-04-18 15:25:19
【问题描述】:
我有一个函数,给定两个集合 A 和 B,如果两个集合中的一个与另一个集合共享至少 50% 的元素,它返回一个有边集 A.union(B),否则返回 False:
def merged_set_or_false(set1, set2):
if **magic**:
return merged_set
else:
return False
现在,我想做的是遍历一个集合列表,直到列表中的两个集合不能再合并。什么是有效的方法?在我看来,它看起来像一个 reduce(),但实际上并没有必要缩减为单个元素。
一个例子:
>>> list_of_sets = [(1,2,3,4),(2,3,4,5),(6,7,8,9)]
>>> len(list_of_sets)
3
>>> new_list = merge_until_possible(list_of_sets)
>>> new_list
[(1,2,3,4,5),(6,7,8,9)]
>>> len(new_list)
2
想法?
编辑 - 2016 年 12 月 4 日 以防万一有人发现它有用,这是我目前解决此问题的正在进行中的解决方案:
def pseudo_reduce(f, list_to_reduce):
"""Perform f on two elements of list per time until possible."""
reducing_is_still_possible = True
exit_loops = False
while reducing_is_still_possible:
initial_list_len = len(list_to_reduce)
for j in range(len(list_to_reduce)):
# If two elements became one in previous iter, we need to break twice
if exit_loops:
exit_loops = False
break
# If j is the last element, break to avoid out of index error
if j == (len(list_to_reduce) - 1):
break
for k in range(j + 1, len(list_to_reduce)):
element_or_false = f(list_to_reduce[j],list_to_reduce[k])
if element_or_false:
# We remove the merged elements and append the new one
del list_to_reduce[k]
del list_to_reduce[j]
list_to_reduce.append(element_or_false)
exit_loops = True
break
if len(list_to_reduce) == initial_list_len:
reducing_is_still_possible = False
return list_to_reduce
【问题讨论】:
-
当有不同的合并路径时,您将需要更具体地了解您想要做什么。例如,{0,1,2}, {1,4}, {3,4} 可能变成 {0,1,2,3,4} 或 {0,1,2}, {1,3,4 } 取决于合并发生的顺序。
-
@DSM,没关系。只要不能再合并,任何解决方案都被认为是正确的。
-
{0,1,2}, {3,4}, {0,1,2,3} 是为什么你不能“有效”地做到这一点 - 例如减少。