【问题标题】:Float values as dictionary key浮点值作为字典键
【发布时间】:2014-07-06 10:31:21
【问题描述】:

我正在开发一个用于分析微量滴定板的课程。样本在单独的文件中描述,条目用于有序字典。其中一个关键是 pH,通常以浮点数形式给出。例如 6.8

我可以使用Decimal('6.8') 将其作为十进制导入,以避免将浮点数作为字典键。另一种解决方案是将点替换为例如 6p8 之类的 p 或在我的示例描述中写 6p8 ,从而从一开始就消除问题。但这会在以后造成麻烦,因为我无法在我的图中绘制 6p8 的 pH 值。

你会如何解决这个问题?

【问题讨论】:

  • 也许你想截断你的浮点数以便在使用关键之前掌握它的质量?
  • 谢谢。我会考虑的。

标签: python dictionary floating-point key


【解决方案1】:

也许您想在使用 is 作为键之前截断浮点数?

可能是这样的:

a = 0.122334
round(a, 4)       #<-- use this as your key?

你的钥匙现在是:

0.1223           # still a float, but you have control over its quality

您可以按如下方式使用它:

dictionary[round(a, 4)]   

检索您的值

【讨论】:

  • 为什么你认为这比只使用圆形浮动更安全?
  • 浮点数也是不可变的。在这种情况下,您的恐惧是错误的,会给您带来性能损失。
  • 四舍五入后,二进制表示是相同的,因此哈希值当然也是。
  • 不错的解决方案。而且很容易。
  • 另外,OP 想要绘制数据,因此他必须重新转换为浮点数,从而增加更多不必要的开销。
【解决方案2】:

使用浮点数作为字典键没有问题。

只需round(n, 1) 即可将它们标准化为您的键空间。例如。

>>> hash(round(6.84, 1))
3543446220
>>> hash(round(6.75, 1))
3543446220

【讨论】:

  • 你的解决方案和 Reblochon 的有什么区别?他建议我应该只使用 round() 而不使用额外的 hash()。我不需要非常高的精度,因为我的 pH 条件总是至少相差 0.1。
  • 我并不是要明确建议您使用hashhash 值是 dict 如何确定键 可能 相等(相等的值 必须 具有相同的散列)。这就是获得 O(1) 性能的方式。我只是在证明哈希值是相同的(当您了解 round 的结果相同时,这一点很明显)
  • @PadraicCunningham,如果您确信这些花车都来自同一个来源并以相同的方式生产,那么您可以摆脱这个问题。但我不会太相信不是来自我控制的来源的数据。
  • @BobStein-VisiBone,如果字典仅依赖于哈希的唯一性,将会非常糟糕。
  • @BobStein-VisiBone,澄清一下 - 哈希值必须相等,但反之则不然。这就是说散列不必是唯一的另一个原因。您可以将通过哈希查找作为过滤器,因此您无需针对每个键进行测试。在哈希过滤器之后,还测试密钥是否相等以清除误报。
【解决方案3】:

另一种选择是使用元组:

dictionary = {(6.8,): 0.3985}
dictionary[(6.8,)]

然后检索值以进行绘图很容易用类似的东西完成

points = [(pH, value) for (pH,), value in dictionary.items()]
    ...

【讨论】:

    【解决方案4】:

    另一个快速的选择是使用浮动字符串

    a = 200.01234567890123456789
    b = {str(a): 1}
    for key in b:
        print(float(key), b[key])
    

    会打印出来

    (200.012345679, 1)
    

    注意a 在小数点后的第十位被截断

    【讨论】:

      【解决方案5】:

      另一种方法是将键作为带有点而不是 p 的字符串输入,然后将它们重新转换为用于绘图的浮点数。

      就个人而言,如果您不坚持使用 dict 格式,我会将数据存储为 pandas 数据框,并将 pH 作为列,因为这些更容易传递给绘图库

      【讨论】:

        【解决方案6】:

        如果您想在程序中的多个位置使用浮点键字典,我可能值得在 new dictionary class (full implementation) 中“隐藏”它应该如何使用(即使用圆角键)的复杂性。

        例子:

        >>> d = FloatKeyDictionary(2, {math.pi: "foo"})
        >>> d
        {3.14: 'foo'}
        
        >>> d[3.1415]
        'foo'
        
        >>> 3.1 in d
        False
        
        >>> d[math.e] = "My hovercraft is full of eels!"
        >>> d
        {3.14: 'foo', 2.72: 'My hovercraft is full of eels!'}
        

        您可以在下面找到大致思路的精简版:

        import abc
        import collections.abc
        
        
        class KeyTransformDictionaryBase(dict, abc.ABC):
        
            @abc.abstractmethod
            def __key_transform__(self, key):
                raise NotImplementedError
        
            def __contains__(self, key):
                return super().__contains__(self.__key_transform__(key))
        
            def __getitem__(self, key):
                return super().__getitem__(self.__key_transform__(key))
        
            def __setitem__(self, key, value):
                return super().__setitem__(self.__key_transform__(key), value)
        
            def __delitem__(self, key):
                return super().__delitem__(self.__key_transform__(key))
        
        
        class FloatKeyDictionary(KeyTransformDictionaryBase):
        
            def __init__(self, rounding_ndigits, data=None):
                super().__init__()
                self.rounding_ndigits = rounding_ndigits
                if data is not None:
                    self.update(data)
        
            def __key_transform__(self, key):
                return round(key, self.rounding_ndigits)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-01-23
          • 1970-01-01
          • 1970-01-01
          • 2015-11-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多