简体   繁体   English

用相同的键排序的Python字典

[英]Python dictionary ordering with equal keys

I thought this must already have been answered, but I couldn't find anything on Google or here. 我认为这肯定已经得到了解答,但我在谷歌或这里找不到任何东西。

I'm aware that, in general, you cannot rely on the ordering of a Python dictionary. 我知道,一般来说,你不能依赖Python字典的排序。 However, if you have two dictionaries with identical keys, can you rely on the values being in the same order as well? 但是,如果您有两个具有相同键的字典,您是否可以依赖于相同顺序的值?

I ask because I'm trying to compare two dictionaries of floating point numbers, so I cannot use dict1==dict2 . 我问,因为我试图比较浮点数的两个字典,所以我不能使用dict1==dict2 My function looks something like this: 我的函数看起来像这样:

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

Is this a dangerous game to play? 这是一场危险的比赛吗? In one test, the order seemed to hold: 在一次测试中,订单似乎成立:

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}

But I don't know if this is something I can count on. 但我不知道这是否值得我依靠。 Other solutions for comparing two dictionaries of floating point numbers are welcome too, of course. 当然,其他用于比较两个浮点数字典的解决方案也是受欢迎的。

Depending on how the dictionaries were built, you can't rely on that. 根据字典的构建方式,您不能依赖它。

some example: 一些例子:

>>> 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 is a much bigger hash table because it has allocated space for 1000 objects while b can only hold about 100 without growing a little. a是一个更大的哈希表,因为它为1000个对象分配了空间,而b只能保持大约100而不会增长一点。 So the way the hashes are stored can change the iteration order 因此存储哈希的方式可以改变迭代顺序

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

This still won't work for numbers smaller than -2 or greater then 2 because you are thinking about epsilon wrongly 仍然不适用于小于-2或大于2因为您错误地考虑了epsilon

Instead you need to choose a way to compare floats that makes sense. 相反,你需要选择一种方法来比较有意义的浮动。 You can choose to use a fixed epsilon, but that will only work up to a point. 您可以选择使用固定的epsilon,但这只会达到一定程度。 floats can be very very big. 花车可能非常大。

It's usually better to use a relative comparison than absolute 使用相对比较通常比使用绝对更好

I'd recommend something like this: 我推荐这样的东西:

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

It's easy to read and it will return False as soon as it notices two values that are not within sys.float_info.epsilon rather than comparing all the values. 它很容易阅读,一旦注意到两个不在sys.float_info.epsilon的值而不是比较所有值,它将返回False

dictionaries are not ordered, they cannot be ordered unless you use a frozen dict which exist in python 3.3 字典不是有序的,除非你使用python 3.3中存在的冻结字典 ,否则不能对它们进行排序

Now to compare keys you could convert the keys into a set: 现在要比较键,您可以将键转换为一组:

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

b == c
True

or you could create a list and order it to compare them, I like more the set approach. 或者你可以创建一个列表并命令它来比较它们,我更喜欢设置方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM