Python 在字典中查找混合类型值的重复项

Python 在字典中查找混合类型值的重复项,python,dictionary,hash,pickle,Python,Dictionary,Hash,Pickle,我想在字典中识别和分组重复的值。为此,我为我的数据集构建了一个伪哈希(更好的读取签名),如下所示: from pickle import dumps taxonomy = {} binder = defaultdict(list) for key, value in ds.items(): signature = dumps(value) taxonomy[signature] = value binder[signature].append(key) 有关具体用

我想在字典中识别和分组重复的值。为此,我为我的数据集构建了一个伪哈希(更好的读取签名),如下所示:

from pickle import dumps
taxonomy = {}
binder = defaultdict(list)
for key, value in ds.items():
    signature = dumps(value)
    taxonomy[signature] = value
    binder[signature].append(key)   
有关具体用例,请参见此

不幸的是,我意识到如果以下语句是
真的

>>> ds['key1'] == ds['key2']
True
这一点不再总是
True

>>> dumps(ds['key1']) == dumps(ds['key2'])
False
我注意到转储输出上的键顺序对于两个dict都不同。如果我将
ds['key1']
ds['key2']
的输出复制/粘贴到新词典中,我可以成功地进行比较

作为一种过度的替代方法,我可以递归遍历我的数据集,并将
dict
实例替换为
orderedict

import copy
def faithfulrepr(od):
    od = od.deepcopy(od)
    if isinstance(od, collections.Mapping):
        res = collections.OrderedDict()
        for k, v in sorted(od.items()):
            res[k] = faithfulrepr(v)
        return repr(res)
    if isinstance(od, list):
        for i, v in enumerate(od):
            od[i] = faithfulrepr(v)
        return repr(od)
    return repr(od)

>>> faithfulrepr(ds['key1']) == faithfulrepr(ds['key2'])
True
我担心这种幼稚的做法,因为我不知道我是否涵盖了所有可能的情况


我还可以使用其他(通用)替代方案吗?

首先要删除对
deepcopy
的调用,这是您的瓶颈:

def faithfulrepr(ds):
    if isinstance(ds, collections.Mapping):
        res = collections.OrderedDict(
            (k, faithfulrepr(v)) for k, v in sorted(ds.items())
        )
    elif isinstance(ds, list):
        res = [faithfulrepr(v) for v in ds]
    else:
        res = ds
    return repr(res)
然而,
sorted
repr
有其缺点:

  • 您无法真正比较自定义类型
  • 不能对不同类型的键使用映射
  • 因此,第二件事是去掉
    faithfulrepr
    ,并将对象与
    \uuuuueq\uuuuu
    进行比较:

    binder, values = [], []
    for key, value in ds.items():
        try:
            index = values.index(value)
        except ValueError:
            values.append(value)
            binder.append([key])
        else:
            binder[index].append(key)
    grouped = dict(zip(map(tuple, binder), values))
    

    因此,您希望每个
    dict
    repr
    相同。。。有什么原因不能只
    加载它们并进行比较吗?是的,使用
    repr
    比使用
    pickle
    容易得多。不幸的是,
    repr
    对象并不总是足以比较两个实例的内容。这就是说,
    repr(ds['key1'])==repr(ds['key2'])
    也会返回
    False
    …我的意思是-你想让
    dict
    对象的一些表示比较相等-可以是JSON/pickled/
    str
    'd/
    repr
    'd等等。。。为什么不把它倒过来再比较一下呢?例如:
    loads(dumps(ds['key1'])==loads(dumps(ds['key2'])
    ?如果你看我在
    binder[signature].append(key)
    附近的例子,我并没有像
    a==b
    那样比较我的字典。因此,在我的示例中,您的解决方案不起作用。