2

我认为这一定已经得到了回答,但我在谷歌或这里找不到任何东西。

我知道,一般来说,您不能依赖 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

4 回答 4

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 个对象而不会增长一点。所以哈希的存储方式可以改变迭代顺序

于 2012-07-19T03:28:50.533 回答
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,但这只能在一定程度上起作用。花车可以非常非常大。

使用相对比较通常比绝对比较好

于 2012-07-19T03:45:15.740 回答
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而不是比较所有值。

于 2012-07-19T03:32:17.310 回答
1

字典没有排序,除非你使用python 3.3 中存在的冻结字典,否则它们不能被排序

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

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

b == c
True

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

于 2012-07-19T03:31:37.793 回答