将整数数组编码为唯一的int

时间:2018-01-23 22:35:19

标签: python arrays numpy

我有一定数量的形式的int数组:

[a,b,c,d,e]

例如:

[2,2,1,1,2]

其中ab可以是0到2的整数,cd可以是0或1,e可以是0到2。

因此,有3 * 3 * 2 * 2 * 3108这种形式的可能数组。

我想为每个数组分配一个0到107的唯一整数代码。

我被卡住了,我想在数组中添加每个数字,但是有两个数组,例如:

[0,0,0,0,1] and [1,0,0,0,0]

都会加1。

有什么建议吗?

谢谢。

6 个答案:

答案 0 :(得分:16)

您可以使用np.ravel_multi_index

>>> {np.ravel_multi_index(j, (3, 3, 2, 2, 3)) for j in itertools.product(*map(range, (3,3,2,2,3)))} == set(range(np.prod((3, 3, 2, 2, 3))))
True

验证:

>>> np.unravel_index(65, dims=(3, 3, 2, 2, 3))
(1, 2, 0, 1, 2)

回到另一个方向:

fileName.contains()

答案 1 :(得分:3)

这有点像将数字从不同大小的数字转换为标准整数。在base-10中,你可以有五个数字,每个数字从0到9,然后你可以通过i = a*10000 + b*1000 + c*100 + d*10 + e*1将它们转换为一个整数。

等效地,对于十进制转换,您可以编写i = np.dot([a, b, c, d, e], bases),其中bases = [10*10*10*10, 10*10*10, 10*10, 10, 1]

你可以用你的基础做同样的事情,除了你的位置引入[3,3,2,2,3]的乘数而不是[10,10,10,10,10]。因此,您可以设置bases = [3*2*2*3, 2*2*3, 2*3, 3, 1](= [36,12,6,3,1]),然后使用i = np.dot([a, b, c, d, e], bases)。请注意,如果a,b,c,d和e落在您指定的范围内,这将始终给出0到107范围内的答案。

要将i转换回数字列表,您可以使用以下内容:

digits = []
remainder = i
for base in bases:
    digit, remainder = divmod(remainder, base)
    digits.append(digit)

另一方面,为了让你的生活变得简单,你可能最好使用Paul Panzer的答案,这几乎可以做同样的事情。 (我之前从未想过n位数字作为n维网格中单元格的坐标,但事实证明它们在数学上是等价的。而np.ravel是一种为每个单元格分配序列号的简单方法。)

答案 2 :(得分:3)

另一种方式,类似于多项式的Horner's method

>>> array = [1, 2, 0, 1, 2]
>>> ranges = (3, 3, 2, 2, 3)
>>> reduce(lambda i, (a, r): i * r + a, zip(array, ranges), 0)
65

展开(&((0 * 3 + 1)* 3 + 2)* 2 + 0)* 2 + 1)* 3 + 2 = 65。

答案 3 :(得分:1)

此数据足够小,您可以简单地枚举它们:

>>> L = [[a,b,c,d,e] for a in range(3) for b in range(3) for c in range(2) for d in range(2) for e in range(3)]
>>> L[0]
[0, 0, 0, 0, 0]
>>> L[107]
[2, 2, 1, 1, 2]

如果你需要走另一条路(从数组到整数),为它创建一个查找字典,这样你就得到O(1)而不是O(n):

>>> lookup = {tuple(x): i for i, x in enumerate(L)}
>>> lookup[1,1,1,1,1]
58

答案 4 :(得分:0)

dot-product的向量设为:

In [210]: a1
Out[210]: array([2, 2, 1, 1, 2])

In [211]: a2
Out[211]: array([1, 0, 1, 1, 0])

In [212]: a1.dot(np.power(10, np.arange(5,0,-1)))
Out[212]: 221120

In [213]: a2.dot(np.power(10, np.arange(5,0,-1)))
Out[213]: 101100

应该产生108个唯一数字 - 使用它们的索引......

答案 5 :(得分:0)

如果数组长度不是很大,您可以先计算出重量,然后使用简单的数学公式来获取ID。 代码如下:

#Test Case
test1 = [2, 2, 1, 1, 2]
test2 = [0, 2, 1, 1, 2]
test3 = [0, 0, 0, 0, 2]

def getUniqueID(target):
    #calculate out the weights first; 
    #When Index=0; Weight[0]=1;
    #When Index>0; Weight[Index] = Weight[Index-1]*(The count of Possible Values for Previous Index);
    weight = [1, 3, 9, 18, 36]
    return target[0]*weight[0] + target[1]*weight[1] + target[2]*weight[2] + target[3]*weight[3] + target[4]*weight[4]

print 'Test Case 1:', getUniqueID(test1)
print 'Test Case 2:', getUniqueID(test2)
print 'Test Case 3:', getUniqueID(test3)

#Output
#Test Case 1: 107
#Test Case 2: 105
#Test Case 3: 72
#[Finished in 0.335s]