Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
重写字典行为Python3_Python_Python 3.x_Numpy - Fatal编程技术网

重写字典行为Python3

重写字典行为Python3,python,python-3.x,numpy,Python,Python 3.x,Numpy,我是Python的初学者,正在尝试使用字典中的搜索函数来搜索具有点坐标(2)的numpy数组的键。所以,我想要的是:一个字典,它的键是numpy数组,值是整数。然后,in运算符将用于使用某种公差度量(numpy.allclose函数)比较键。我知道numpy数组不是哈希表,因此我必须重写getitem和setitem函数(基于我在中找到的内容)。但是如何使这些哈希值能够作为键添加到字典中呢?在这种情况下,如何覆盖in运算符的行为 谢谢你的帮助 使用2元组的浮点作为键,而不是numpy数组。元组是

我是Python的初学者,正在尝试使用字典中的搜索函数来搜索具有点坐标(2)的numpy数组的键。所以,我想要的是:一个字典,它的键是numpy数组,值是整数。然后,in运算符将用于使用某种公差度量(numpy.allclose函数)比较键。我知道numpy数组不是哈希表,因此我必须重写getitemsetitem函数(基于我在中找到的内容)。但是如何使这些哈希值能够作为键添加到字典中呢?在这种情况下,如何覆盖in运算符的行为


谢谢你的帮助

使用2元组的浮点作为键,而不是numpy数组。元组是可散列的,因为它们是不可变的

Python字典在后台使用一个键来快速查找键

编写一个接近函数的
并不是那么难

def closeto(a, b, limit=0.1):
    x, y = a
    p, q = b
    return (x-p)**2 + (y-q)**2 < limit**2

将数组转换为元组,元组可以散列:

In [18]: a1 = np.array([0.5, 0.5])

In [19]: a2 = np.array([1.0, 1.5])

In [20]: d = {}

In [21]: d[tuple(a1)] = 14

In [22]: d[tuple(a2)] = 15

In [23]: d
Out[23]: {(0.5, 0.5): 14, (1.0, 1.5): 15}

In [24]: a3 = np.array([0.5, 0.5])

In [25]: a3 in d
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-25-07c81d61b999> in <module>()
----> 1 a3 in d

TypeError: unhashable type: 'numpy.ndarray'

In [26]: tuple(a3) in d
Out[26]: True
[18]中的
:a1=np.数组([0.5,0.5])
[19]中:a2=np.数组([1.0,1.5])
在[20]中:d={}
在[21]中:d[元组(a1)]=14
In[22]:d[元组(a2)]=15
In[23]:d
Out[23]:{(0.5,0.5):14,(1.0,1.5):15}
[24]中:a3=np.数组([0.5,0.5])
In[25]:a3 In d
---------------------------------------------------------------------------
TypeError回溯(最近一次调用上次)
在()
---->1 a3英寸d
TypeError:不可损坏的类型:“numpy.ndarray”
[26]中:d中的元组(a3)
Out[26]:对

不幸的是,由于您希望对比较应用容差,因此您没有太多选择,只能迭代所有键以查找“接近”匹配,无论您是将其实现为函数还是内嵌。

Numpy数组不可散列,但元组是可散列的。因此,如果将数组转换为元组,则可以对其进行散列。从理论上讲,如果您事先对它进行四舍五入,您可以利用快速查找,因为您现在有离散点。但在重传过程中会遇到分辨率问题,因为四舍五入是用十进制基数完成的,而数字是二进制存储的。可以通过将其转换为一个缩放整数来避免这种情况,但这会让一切都慢一点

最后,您只需编写一个在数组和元组之间来回转换的类,就可以了。
实现可以如下所示:

import numpy as np

class PointDict(dict):

    def __init__(self, precision=5):
        super(PointDict, self).__init__()
        self._prec = 10**precision

    def decode(self, tup):
        """
        Turns a tuple that was used as index back into a numpy array.
        """
        return np.array(tup, dtype=float)/self._prec

    def encode(self, ndarray):
        """
        Rounds a numpy array and turns it into a tuple so that it can be used
        as index for this dict.
        """
        return tuple(int(x) for x in ndarray*self._prec)

    def __getitem__(self, item):
        return self.decode(super(PointDict, self).__getitem__(self.encode(item)))

    def __setitem__(self, item, value):
        return super(PointDict, self).__setitem__(self.encode(item), value)

    def __contains__(self, item):
        return super(PointDict, self).__contains__(self.encode(item))

    def update(self, other):
        for item, value in other.items():
            self[item] = value

    def items(self):
        for item in self:
            yield (item, self[item])

    def __iter__(self):
        for item in super(PointDict, self).__iter__():
            yield self.decode(item)

查找大量点时,使用矢量化批写入/查找的纯numpy解决方案可能更好。但是,此解决方案易于理解和实现。

由于您不是该类型的作者,因此无法使numpy数组可散列。您可以创建一个子类型,该子类型继承自numpy数组,并且是可散列的。您能告诉我们更多关于您希望使用该数据结构实现的功能吗?我打赌有一种更好的方法可以用numpy实现这一点。我需要检查我试图添加的一个键(numpy数组)是否已经存在于所述数组中,如果不存在,则只添加该dict条目。你能用一些示例数据给出一个最简单的例子吗?当然,假设我有一个dict={[0.50.5]:13[1.1.5]:14},并且我有一个新的numpy数组[0.5 0.5]。我想(有效地)在该dict字典中搜索此“new”键,只添加条目[0.5 0.5](带有相应的整数值)如果dict中不存在,我需要使用numpy数组,所以我无法更改。似乎为了找到一个对象是否在这个字典中,你必须遍历所有对象,使用字典的目的不是为了快速访问吗?有没有一种聪明的方法来散列numpy数组?@Gonçalovalent Python使用散列键的原因是检查dict中是否存在键(操作员中的
)在后台使用a会更快。因此,您不必检查所有项目。因此,除了我需要使用allcose numpy函数比较成员身份这一事实之外,这一点也可以。allcose numpy函数测试容差值内的数组。必须有更智能的方法来完成此操作。重写contains函数是否可以防止出现这样的类型错误当询问a3是否在d中时显示?事实仍然是,无论如何实现它,您都必须对新键和所有现有键应用
allclose
,直到找到一个足够接近的键或从键的末端运行(如果未找到匹配项).但使用字典的目的是能够快速找到元素,不是吗?我希望使用哈希函数而不是线性时间在固定时间内找到它。当然可以,但dicts使用键的精确匹配。因此,您需要定义一个哈希函数,为所有“close”生成相同的值你的点的值。祝你好运-我不是说这是不可能的,但我不打算尝试。一种可能的转换可能会有帮助,就是在应用哈希之前,将键值转换为一些概念网格上的点,我想,但这不会给你与
allclose
相同的结果。注意任何包含你能告诉我“矢量化批量写入/查找”是什么意思吗?我在哪里可以读到这方面的内容?谢谢!@Gonçalovalent我的意思是,您可以同时查找或更新多个点。当您可以对操作进行矢量化时,Numpy是最快的,这意味着使用数组进行索引并同时分配或更改多个条目。这里的问题是设计一种聪明的方法来保存这些项以及t继承人的值,以便我们可以利用它。您不会得到O(1)查找,但O(log(n))可能是可能的。。。
import numpy as np

class PointDict(dict):

    def __init__(self, precision=5):
        super(PointDict, self).__init__()
        self._prec = 10**precision

    def decode(self, tup):
        """
        Turns a tuple that was used as index back into a numpy array.
        """
        return np.array(tup, dtype=float)/self._prec

    def encode(self, ndarray):
        """
        Rounds a numpy array and turns it into a tuple so that it can be used
        as index for this dict.
        """
        return tuple(int(x) for x in ndarray*self._prec)

    def __getitem__(self, item):
        return self.decode(super(PointDict, self).__getitem__(self.encode(item)))

    def __setitem__(self, item, value):
        return super(PointDict, self).__setitem__(self.encode(item), value)

    def __contains__(self, item):
        return super(PointDict, self).__contains__(self.encode(item))

    def update(self, other):
        for item, value in other.items():
            self[item] = value

    def items(self):
        for item in self:
            yield (item, self[item])

    def __iter__(self):
        for item in super(PointDict, self).__iter__():
            yield self.decode(item)