random.shuffle() 的逆操作是什么?
我有一个函数,为了简单起见,我叫它 shuffler。这个函数接收一个列表,然后给它一个随机种子17,最后把这个列表打乱后打印出来。
def shuffler( n ):
import random
random.seed( 17 )
print( random.shuffle( n ) )
我该如何创建另一个函数,叫做 unshuffler,它可以把 shuffler() 返回的那个打乱的列表“还原”回我输入的列表,前提是我知道那个种子呢?
4 个回答
2
在Python3中:
import random
import numpy as np
def shuffle_forward(l):
order = list(range(len(l)); random.shuffle(order))
return list(np.array(l)[order]), order
def shuffle_backward(l, order):
l_out = [0] * len(l)
for i, j in enumerate(order):
l_out[j] = l[i]
return l_out
2
用你关心的那个种子重新设置随机生成器,然后把列表1, 2, ..., n打乱。这可以让你准确知道在打乱后每个数字最终的位置。
3
这里有两个函数可以满足你的需求:
import random
import numpy as np
def shuffle_forward(l):
order = range(len(l)); random.shuffle(order)
return list(np.array(l)[order]), order
def shuffle_backward(l, order):
l_out = [0] * len(l)
for i, j in enumerate(order):
l_out[j] = l[i]
return l_out
示例
l = range(10000); random.shuffle(l)
l_shuf, order = shuffle_forward(l)
l_unshuffled = shuffle_backward(l_shuf, order)
print l == l_unshuffled
#True
8
我想分享一个更适合使用numpy的函数式编程方法的答案。最终,这种解决方案应该是最快的,因为它能利用numpy内部的优化。而且,通过使用像numba这样的项目,还可以进一步优化性能。总的来说,这种方法应该比在python中使用传统的循环结构快得多。
import numpy as np
original_data = np.array([23, 44, 55, 19, 500, 201]) # Some random numbers to represent the original data to be shuffled
data_length = original_data.shape[0]
# Here we create an array of shuffled indices
shuf_order = np.arange(data_length)
np.random.shuffle(shuf_order)
shuffled_data = original_data[shuf_order] # Shuffle the original data
# Create an inverse of the shuffled index array (to reverse the shuffling operation, or to "unshuffle")
unshuf_order = np.zeros_like(shuf_order)
unshuf_order[shuf_order] = np.arange(data_length)
unshuffled_data = shuffled_data[unshuf_order] # Unshuffle the shuffled data
print(f"original_data: {original_data}")
print(f"shuffled_data: {shuffled_data}")
print(f"unshuffled_data: {unshuffled_data}")
assert np.all(np.equal(unshuffled_data, original_data))