用相同的键排序的Python字典

时间:2012-07-19 03:19:44

标签: python dictionary floating-point hashmap

我认为这肯定已经得到了解答,但我在Google或此处找不到任何内容。

我知道,一般来说,你不能依赖Python字典的排序。但是,如果您有两个带有相同键的词典,那么您是否可以依赖相同顺序的值?

我问,因为我试图比较浮点数的两个字典,所以我不能使用dict1==dict2。我的功能看起来像这样:

def _compare_dict(self, d1, d2):
    """
    Compares two dictionaries of floating point numbers
    for equality.
    """
    if d1.keys() != d2.keys():
        return False

    zipped = zip(d1.itervalues(), d2.itervalues())
    return len(filter(lambda x: abs(x[0] - x[1]) > sys.float_info.epsilon, zipped)) == 0

这是一场危险的比赛吗?在一次测试中,订单似乎成立:

In [126]: d1={'a': 3, 'b': 2, 'c': 10}
In [127]: d2={'b': 10, 'c': 7, 'a': 2}

In [128]: d1
Out[128]: {'a': 3, 'b': 2, 'c': 10}

In [129]: d2
Out[129]: {'a': 2, 'b': 10, 'c': 7}

但我不知道这是否值得我依赖。当然,其他用于比较两个浮点数字典的解决方案也是受欢迎的。

4 个答案:

答案 0 :(得分:8)

根据词典的构建方式,你不能依赖它。

一些例子:

>>> a = dict.fromkeys(range(1000))
>>> b = dict.fromkeys(range(500,600))
>>> for i in range(500):
    del a[i]

>>> for i in range(600,1000):
    del a[i]

>>> all(i==j for i,j in zip(a,b))
False
>>> a == b
True

a是一个更大的哈希表,因为它为1000个对象分配了空间,而b只能容纳大约100个而不会增长一点。因此存储哈希的方式可以改变迭代顺序

答案 1 :(得分:3)

def _compare_dict(self, d1, d2):
    """
    Compares two dictionaries of floating point numbers
    for equality.
    """
    if len(d1) != len(d2): # comparing `.keys()` is futile and slow
        return False
    try:
        return all(abs(d1[k] - d2[k]) < sys.float_info.epsilon for k in d1)
    except KeyError:
        return False

对于小于-2或大于2的数字,此仍然无效,因为您错误地考虑了epsilon

相反,您需要选择一种方法来比较有意义的浮点数。您可以选择使用固定的epsilon,但这只会达到一定程度。花车可能非常大。

使用相对比较通常比绝对

更好

答案 2 :(得分:2)

我建议这样的事情:

def _compare_dict(self, d1, d2):
    if set(d1.keys()) != set(d2.keys()):
        return False

    for key in d1:
        if abs(d1[key]-d2[key]) > sys.float_info.epsilon:
            return False

    return True

它易于阅读,只要注意到两个不在False范围内的值而不是比较所有值,它就会返回sys.float_info.epsilon

答案 3 :(得分:1)

字典未订购,除非您使用python 3.3中存在的frozen dict,否则无法对它们进行排序

现在要比较键,您可以将键转换为一组:

a = {'a': 0, 'b': 1}
b = set(a)
c = set(a.keys())  # just another way to be clearer

b == c
True

或者你可以创建一个列表并命令它来比较它们,我更喜欢设置方法。