以下是使用tuple
的一种方法:
>>> import numpy as np
>>> t = [np.asarray([1, 2, 3, 4]),
np.asarray([1, 2, 3, 4]),
np.asarray([1, 1, 3, 4])]
>>> map(np.asarray, set(map(tuple, t)))
[array([1, 1, 3, 4]), array([1, 2, 3, 4])]
如果您的数组是多维的,那么首先将它们展平为一个1乘以任何数的数组,然后使用相同的思路,在最后重新整形它们:
def to_tuple(arr):
return tuple(arr.reshape((arr.size,)))
def from_tuple(tup, original_shape):
np.asarray(tup).reshape(original_shape)
例子:
In [64]: t = np.asarray([[[1,2,3],[4,5,6]],
[[1,1,3],[4,5,6]],
[[1,2,3],[4,5,6]]])
In [65]: map(lambda x: from_tuple(x, t[0].shape), set(map(to_tuple, t)))
Out[65]:
[array([[1, 2, 3],
[4, 5, 6]]),
array([[1, 1, 3],
[4, 5, 6]])]
另一种选项是创建一个
pandas.DataFrame
,将你的
ndarrays
转换为行(如果需要,通过重塑),并使用 pandas 内置的方法对行进行去重。
In [34]: t
Out[34]: [array([1, 2, 3, 4]), array([1, 2, 3, 4]), array([1, 1, 3, 4])]
In [35]: pandas.DataFrame(t).drop_duplicates().values
Out[35]:
array([[1, 2, 3, 4],
[1, 1, 3, 4]])
总体上,我认为尝试使用
tostring()
作为准哈希函数是个坏主意,因为你需要更多的样板代码来防止在某些
dict
中分配它们的“哈希”键之后,内容被改变的可能性。如果数据的重塑和转换成元组过程太慢,那么我的感觉是这暴露了一个更根本的问题:应用程序没有围绕需求(如去重)进行良好设计,并试图将其塞入运行在内存中的Python进程中,这可能不是正确的方式。此时,我会停下来考虑像Cassandra这样的东西,它可以轻松地在浮点(或其他)数据的大列(或多维数组)之上构建数据库索引,这可能是更明智的方法。
list
和ndarray
是 可变的 -- 如果你试图定义一个list
的哈希值,它需要基于该list
内容的哈希值工作 -- 但如果内容可以改变,因为它是可变的,那么数组内容的哈希值可能会突然变得不正确。 - elyL
和通过L.values
将所有内容转储到list
之间没有对L
进行任何处理,否则这不安全可靠。在这些步骤之间,您可以访问和修改L [a.tostring()]
,以便该键的值与a
的字符串化不同,例如,如果a
是2-D:L [a.tostring()] [0,0] = np.NaN
。我认为使用tuple
的单行代码在这方面更安全一些(没有中间机会进行突变)。 - ely