Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 将项目分组为子集(幂集)_Algorithm_Combinations_Powerset - Fatal编程技术网

Algorithm 将项目分组为子集(幂集)

Algorithm 将项目分组为子集(幂集),algorithm,combinations,powerset,Algorithm,Combinations,Powerset,假设我有以下几点: john: [a, b, c, d] bob: [a, c, d, e] mary: [a, b, e, f] [a] : [j, b, m] [b] : [j, m] [c] : [j, b] [d] : [j, b] [e] : [b, m] [f] : [m] 或者稍微重新格式化,以便您可以轻松查看分组: john: [a, b, c, d] bob: [a, c, d, e] mary: [a, b, e, f] 生成以下分组的最常见或最有

假设我有以下几点:

john: [a, b, c, d]
bob:  [a, c, d, e]
mary: [a, b, e, f]
[a] : [j, b, m]
[b] : [j, m]
[c] : [j, b]
[d] : [j, b]
[e] : [b, m]
[f] : [m]
或者稍微重新格式化,以便您可以轻松查看分组:

john: [a, b, c, d]
bob:  [a,    c, d, e]
mary: [a, b,       e, f]
生成以下分组的最常见或最有效的算法是什么

[john, bob, mary]: [a]
[john, mary]:      [b]
[john, bob]:       [c,d]
[bob, mary]:       [e]
[mary]:            [f]
[john]:            []
[bob]:             []
快速谷歌搜索后,上面的键似乎代表了“电源组”。因此,我计划进行以下impl:

1) 生成幂集{{j,b,m},{j,m},{j,b}{b,m},{m},{j},{b}//j=john,b=bob,m=mary

2) 生成所有字母的集合:{a,b,c,d,e,f}

3) 迭代子集,对于每个字母,查看该子集的所有元素中是否存在字母

所以

有更好的解决办法吗

编辑:上述算法存在缺陷。例如,{j,m}还将包含我不想要的“a”。我想我可以简单地修改它,以便在每次迭代中,我也检查这个字母是否“不在”不在这个集合中的元素中。所以在这种情况下,我还要检查:

if b does not contain a

您可以使用两个地图/字典来实现这一点,其中一个是另一个的“反向”。对于第一个映射,“key”是名称,“value”是字符列表。第二个映射将字母作为键,并将与之关联的名称列表作为值

用Python

nameDict = {'john' : ['a', 'b', 'c', 'd'], 'bob' : ['a', 'c', 'd', 'e'], 'mary' : ['a', 'b', 'e', 'f']}

reverseDict = {}
for key,values in nameDict.items():
    for v in values:
        if v in reverseDict.keys():
            reverseDict[v].append(key)
        else:
            reverseDict[v] = [key] # If adding v to dictionary for the first time it needs to be as a list element

# Aggregation
finalDict = {}
for key,values in reverseDict.items():
    v = frozenset(values)
    if v in finalDict.keys():
        finalDict[v].append(key)
    else:
        finalDict[v] = [key] 
这里,reverseDict包含您想要的与a->[john,bob,mary],b->[john,mary]等的映射。您还可以通过检查reverseDict['a']返回的列表是否包含john来检查john是否不包含a

[编辑]将聚合添加到FinalAct中

您可以将frozensets用作字典键,这样finalDict现在就包含正确的结果。打印词典:

frozenset({'bob', 'mary'})
['e']

frozenset({'mary'})
['f']

frozenset({'john', 'bob'})
['c', 'd']

frozenset({'john', 'mary'})
['b']

frozenset({'john', 'bob', 'mary'})
['a']
步骤3(在子集上迭代)将是低效的,因为它会对幂集中的每个元素执行“j包含a”或“a不在j中”

以下是我的建议:

1) 生成幂集{{j,b,m},{j,m},{j,b}{b,m},{m},{j},{b}。您不需要这个步骤,因为您不关心最终输出中的空映射

2) 迭代原始数据结构中的所有元素,并构造以下内容:

john: [a, b, c, d]
bob:  [a, c, d, e]
mary: [a, b, e, f]
[a] : [j, b, m]
[b] : [j, m]
[c] : [j, b]
[d] : [j, b]
[e] : [b, m]
[f] : [m]
3) 颠倒上述结构和聚合(使用[j,b,…]的映射到[a,b,…]的列表应该可以做到这一点)得到:

[j, b, m] : [a]
[j, m] : [b]
[j, b] : [c, d]
[b, m] : [e]
[m] : [f]
4) 将3与1进行比较以填充剩余的空映射

编辑: 这是Java中的完整代码


谢谢,我相信我的困惑是聚合步骤。我不确定是否使用集合作为地图的键。这有什么问题吗?我相信我可以使用guava和apache commons中的多键映射,但我最初计划在JS浏览器中这样做。@nogridbag设置为映射的键是可以的,只要在将其作为键添加到映射后该集不会更改。我认为在多键贴图中,键的顺序很重要。如果键的顺序很重要,那么您可能必须在生成键之前进行排序。谢谢,这很接近,但缺少聚合步骤。例如,您的代码将输出c->{b,j}和d->{b,j},而我需要{b,j}->[c,d]@nogridbag。我认为聚合可以通过制作另一个反向映射来完成,这次是反向指令。这样,键{b,j}将具有相应的值[c,d]。Tim,现在还早,我还没有喝咖啡,但我相信你的聚合步骤只会返回原始数据集:nameDict:)@nogridbag,这会教我不要测试我的答案!我已经使用Frozenset更新了我的答案,现在它产生了正确的结果。
[bob] : []
[john] : []
[bob, mary] : [e]
[bob, john] : [d, c]
[bob, john, mary] : [a]
[mary] : [f]
[john, mary] : [b]