Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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
Python 找到使每个dict在多个dict中唯一的最小键数_Python_Algorithm_Dictionary_Filter_Set - Fatal编程技术网

Python 找到使每个dict在多个dict中唯一的最小键数

Python 找到使每个dict在多个dict中唯一的最小键数,python,algorithm,dictionary,filter,set,Python,Algorithm,Dictionary,Filter,Set,我正试图找到以下问题的有效解决方案: 我有一个字典列表,每一本字典都有与另一本相同的键集。关联值在字典之间可以相等。我试图找到最小键数及其关联值,这将使每个字典唯一 例如,对于包含三个词典的列表: list = [a, b, c] where a = {"key1": "alpha", "key2": "beta", "key3": "gamma"} b = {"key1": "alpha", "key2": "beta", "key3": "eta"} c = {"key1": "alp

我正试图找到以下问题的有效解决方案:

我有一个字典列表,每一本字典都有与另一本相同的键集。关联值在字典之间可以相等。我试图找到最小键数及其关联值,这将使每个字典唯一

例如,对于包含三个词典的列表:

list = [a, b, c]

where 

a = {"key1": "alpha", "key2": "beta", "key3": "gamma"}
b = {"key1": "alpha", "key2": "beta", "key3": "eta"}
c = {"key1": "alpha", "key2": "zeta", "key3": "eta"}
所有三个字典都具有相同的键1值,因此可以消除该键,因为它的包含并不确定字典的唯一性。另一方面,key2和key3必须同时包括在内,因为它们的集合使得各自的字典是唯一的

a = {"key2": "beta", "key3": "gamma"}
b = {"key2": "beta", "key3": "eta"}
c = {"key2": "zeta", "key3": "eta"}
我假设我在字典列表中循环,因此可以在迭代中使用例如collections.Counter列表中字典的数量与键的数量是一个变量。我希望尽可能少地遍历列表(例如,在更新一个或多个计数器时迭代一次)。我相当肯定有一个适合这个问题的算法,但无法用我的搜索关键字找到它


编辑:每个最终dict必须与其他dict具有相同的键。因此,为每个dict保留一组不同的键不是一个选项

如果每个最终dict必须与所有其他dict具有相同的键,唯一的解决方案是删除所有dict中相同的键

您可以通过循环第一个dict并将所有相同的键添加到列表中来实现这一点。然后在最后从dicts中删除保存列表中的所有键

def process_lists(lsts):
    first = lsts[0]
    to_remove = []
    for key in first:
        if all(first[key] == o[key] for o in lsts[1:]):
           to_remove.append(key)
    return [{k: v for k, v in lst.items() if k not in to_remove} for lst in lsts]

process_lists([a, b, c])
这个问题是,通过减少到和从。给定问题的一个实例,我们可以在多项式时间内构造一个多项式大小的集合覆盖问题实例,反之亦然

  • 为了把你的问题减少到集合覆盖,取所有无序对的集合,比如(a,b),(a,c),(b,c);对于每个键,构造该键区分的一组对。区分所有原始字典对的最小键集是这些集合的最小选择

  • 为了减少问题的集合覆盖,给定一个集合{1,2,…,n}和一个子集集合,构造名为a1,b1,a2,b2,…,an,bn的2n个字典。对于每个子集,添加一个键,使该键在每个字典bk中的值为1,其中k在子集中,在每个其他字典中的值为0。在每个字典ak和bk中再添加一个值为k的键。区分所有对的最小键集必然包括最后一个键,但剩余键对应于原始集合覆盖实例的最小集合选择


因此,没有已知的算法可以在多项式时间内解决您的问题。您的问题可以通过a解决,但您不太可能找到比回溯更有效的算法。

精确解是NP难的,但为了获得一个合适的近似值,您可以尝试ID3算法的一种变体来创建决策树:

这种情况的不同之处在于,您必须在所有分支中拾取相同的属性,因此其工作原理如下:

  • 从一套所有字典开始
  • 对于每个属性,计算所有集合中其值的熵之和。 公式在链接文章中
  • 根据所选属性对集合进行分区,并放弃仅包含一个字典的所有集合
  • 如果仍有要分区的集合,请返回(2)

  • 我很高兴其他答案证实了我的猜测,这是一个NP完全问题。目前还没有已知的方法,在最坏的情况下,尝试所有可能的密钥子集

    这是我的算法,它在
    O(n^2*2^k)
    时间和
    O(nk^2+2^k)
    空间中运行,其中
    n
    是列表中的项目数,
    k
    是每个项目的属性数

    只要
    2^k
    <
    n^2
    ,这将在大约多项式时间内运行

    def get_unique_key_值(objs):
    key=get_unique_key(objs)
    返回[{k:obj[k]for k in key}for obj in objs]
    def获取唯一密钥(objs):
    返回get_unique_key_set(objs,{k代表obj中的obj,k代表obj},[])
    def获取唯一密钥集(OBJ、密钥、测试密钥):
    如果len(key)==0或并非所有_唯一(objs):
    #关键点是空集或关键点的子集
    #不保证唯一性
    返回错误
    #唯一密钥所需的最小密钥数
    最佳键集=设置(键)
    #每次删除一个键,并检查
    #项目仍然是独一无二的
    对于del_键入键:
    tmp_键=设置(键)
    tmp_键。移除(删除键)
    #如果我们已经测试过这个子集,请跳过它及其所有子项
    如果tmp_键在测试_键中:
    持续
    #跟踪我们已经测试过的子集,这样我们就不会重新测试它们——显著的微调
    测试的\u键。追加(tmp\u键)
    #仅使用当前关键帧集生成对象列表
    tmp_objs=[{k:obj[k]表示tmp_键中的k}表示objs中的obj]
    #继续从当前子集中删除关键点,直到找到子集为止
    #大小为1,或者当前tmp_键是最佳的
    tmp_密钥集=获取唯一密钥集(tmp_objs、tmp_密钥、测试密钥)
    如果tmp_key_set==False:
    持续
    如果len(tmp密钥集)