很大范围内随机置换中元素的索引

时间:2019-05-02 17:48:22

标签: python

我正在处理很大范围的值(0至大约10 ^ 6128),并且我需要Python中的一种方法来执行双向查询,并随机排列范围。

具有较小数据集的示例:

import random

values = list(range(10))  # the actual range is too large to do this
random.shuffle(values)

def map_value(n):
    return values[n]

def unmap_value(n):
    return values.index(n)

我需要一种方法来实现具有上述很大范围内的值的map_valueunmap_value方法。

1 个答案:

答案 0 :(得分:0)

创建10 ** 6128个值的固定排列非常昂贵-从内存角度考虑。

您可以随时从自己的范围中创建值,并将它们存储在一个/两个字典中。

如果您只绘制比较少的值,一则字典就足够了;如果您有很多值,则可能需要2来更快地查找。

本质上是您

  • 查找值(如果不存在)生成索引,将其存储并返回
  • 查找索引(如果不存在),生成一个值,将其存储并返回

使用固定的随机种子应产生相同的序列:

import random

class big_range():
    random.seed(42) 
    pos_value = {}
    value_pos = {}

    def map_value(self, n):
        p = big_range.value_pos.get(n)
        while p is None:
            p = random.randrange(10**6128) # works, can't use random.choice(range(10**6128))
            if p in big_range.pos_value:
                p = None
            else:
                big_range.pos_value[p]=n
                big_range.value_pos[n]=p
        return p


    def unmap_value(self, n):
        p = big_range.pos_value.get(n)
        while p is None:
            p = random.randrange(10**6128) # works, can't use random.choice(range(10**6128)) 
            if p in big_range.pos_value:
                p = None
            else:
                big_range.pos_value[n]=p
                big_range.value_pos[p]=n
        return p

br = big_range()

for i in range(10):
    print(br.map_value(i))

print(big_range.pos_value)  
print(big_range.value_pos) 

输出:

胡言乱语的单数...但是有效。

由于查找原因,每个数字存储两次(一次存储为pos:number,一次存储为number:pos)。您可能要检查在内存耗尽之前可以生成多少个数字。

您只能使用一个字典,但是在这种情况下,查找 value 到索引不是O(1)而是O(n),因为您需要遍历dict.items()到找到该值并返回索引。

如果您在之间进行其他随机操作,则重复性会中断,因为您更改了随机的“状态”-您可能需要使用random.getstate() / random.setstate()在类内部进行更多封装和状态维护,以存储之后的最后一个状态以及生成新的随机数...

如果您查找大多数值,那么简单地将循环索引从0保留到10 ** 6128 ...,将花费越来越长的时间来生成“不存在”。


这有点脆弱,更是一种思想实验-我不知道为什么需要一个10 ** 6128的数字范围...