洗牌然后取消洗牌 python 列表的好方法
A good way to shuffle and then unshuffle a python list
假设我有一个元组列表
l=[(1,2),(3,4),(5,6),(7,8),(9,10)]
我想按照特定规则打乱值,以便在我打乱列表后可以使用相同的方法将其取消打乱。
一个例子是,我将整个列表向右移动 1 个位置,然后我可以将打乱的列表向左移动一个位置,这样我就可以获得原始列表。
但这看起来有点简单,所以我想知道他们是否有更有创意的方法来做到这一点
编辑:我的想法是,如果我将打乱的列表发送给某人,他可以在不知道原始列表的情况下将其重新打乱,只知道打乱的方法
我想你可以应用任何你喜欢的随机播放,只要你可以播种你的随机源。
取一个包含数字 0 到 n 的列表,然后将其打乱。使用此列表的顺序来洗牌您的元组列表,例如如果洗牌后列表的第一个元素是 5
,那么洗牌后的元组列表中的第一个元素是 l[5]
。然后你可以做相反的事情:你的洗牌元组列表中的第一个元素是你的未洗牌元组列表中的第 5 个元素。
如果您为随机源播种,您可以通过 运行 在相同的 0 到 n 列表上进行相同的随机播放来重新创建已随机播放的数字列表。然后,您可以像以前一样使用它来取消打乱您的打乱的元组列表。
编辑:trincot 的回答实现了这个想法,但有工作示例代码。
您在寻找 deque
吗?
from collections import deque
d = deque([(1,2),(3,4),(5,6),(7,8),(9,10)])
d.rotate(1)
deque([(9, 10), (1, 2), (3, 4), (5, 6), (7, 8)])
d.rotate(-1)
deque([(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)])
您可以选择某种算法来确定可以从列表本身派生的种子,而不取决于其顺序。
对于示例数据结构,种子可以是所有值的总和。然后使用该种子,您将生成从 0 到 n-1 的随机(但确定性)数字排列。然后可以将该排列用作洗牌和取消洗牌函数的基础:
import random
def getperm(l):
seed = sum(sum(a) for a in l)
random.seed(seed)
perm = list(range(len(l)))
random.shuffle(perm)
random.seed() # optional, in order to not impact other code based on random
return perm
def shuffle(l):
perm = getperm(l)
l[:] = [l[j] for j in perm]
def unshuffle(l):
perm = getperm(l)
res = [None] * len(l)
for i, j in enumerate(perm):
res[j] = l[i]
l[:] = res
调用示例:
l=[(1,2),(3,4),(5,6),(7,8),(9,10)]
print(l)
shuffle(l)
print(l) # shuffled
unshuffle(l)
print(l) # the original
假设我有一个元组列表
l=[(1,2),(3,4),(5,6),(7,8),(9,10)]
我想按照特定规则打乱值,以便在我打乱列表后可以使用相同的方法将其取消打乱。
一个例子是,我将整个列表向右移动 1 个位置,然后我可以将打乱的列表向左移动一个位置,这样我就可以获得原始列表。
但这看起来有点简单,所以我想知道他们是否有更有创意的方法来做到这一点
编辑:我的想法是,如果我将打乱的列表发送给某人,他可以在不知道原始列表的情况下将其重新打乱,只知道打乱的方法
我想你可以应用任何你喜欢的随机播放,只要你可以播种你的随机源。
取一个包含数字 0 到 n 的列表,然后将其打乱。使用此列表的顺序来洗牌您的元组列表,例如如果洗牌后列表的第一个元素是 5
,那么洗牌后的元组列表中的第一个元素是 l[5]
。然后你可以做相反的事情:你的洗牌元组列表中的第一个元素是你的未洗牌元组列表中的第 5 个元素。
如果您为随机源播种,您可以通过 运行 在相同的 0 到 n 列表上进行相同的随机播放来重新创建已随机播放的数字列表。然后,您可以像以前一样使用它来取消打乱您的打乱的元组列表。
编辑:trincot 的回答实现了这个想法,但有工作示例代码。
您在寻找 deque
吗?
from collections import deque
d = deque([(1,2),(3,4),(5,6),(7,8),(9,10)])
d.rotate(1)
deque([(9, 10), (1, 2), (3, 4), (5, 6), (7, 8)])
d.rotate(-1)
deque([(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)])
您可以选择某种算法来确定可以从列表本身派生的种子,而不取决于其顺序。
对于示例数据结构,种子可以是所有值的总和。然后使用该种子,您将生成从 0 到 n-1 的随机(但确定性)数字排列。然后可以将该排列用作洗牌和取消洗牌函数的基础:
import random
def getperm(l):
seed = sum(sum(a) for a in l)
random.seed(seed)
perm = list(range(len(l)))
random.shuffle(perm)
random.seed() # optional, in order to not impact other code based on random
return perm
def shuffle(l):
perm = getperm(l)
l[:] = [l[j] for j in perm]
def unshuffle(l):
perm = getperm(l)
res = [None] * len(l)
for i, j in enumerate(perm):
res[j] = l[i]
l[:] = res
调用示例:
l=[(1,2),(3,4),(5,6),(7,8),(9,10)]
print(l)
shuffle(l)
print(l) # shuffled
unshuffle(l)
print(l) # the original