我正在处理很大范围的值(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_value
和unmap_value
方法。
答案 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的数字范围...