random.shuffle() 的逆操作是什么?

11 投票
4 回答
8219 浏览
提问于 2025-04-29 19:13

我有一个函数,为了简单起见,我叫它 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))

撰写回答