随机从列表中选择一个不同的对项
import random
x = ['A','B','C','D','E','F',
'G','H','I','J','K','L',
'M','N','O','P','Q','R',
'S','T','U','V','W','X',
'Y','Z']
y1 = random.sample(x, 2)
y2 = random.sample(x, 2)
y3 = random.sample(x, 2)
y4 = random.sample(x, 2)
y5 = random.sample(x, 2)
查询
如上所示,我选择5个随机样本的组合和变量下声明它们y'x'
。
为了改进我的代码,我想这样做,但要确保列表中的项目在所有变量输出中都不会出现一次以上,其中所有组合都是不同的且不重复的。我希望能够实现这一点,而不必从列表中删除项目,因为它稍后在代码中重用。
期望输出(实施例):
>>> y1
['A', 'Q']
>>> y2
['E', 'K']
>>> y3
['C', 'O']
>>> y4
['Z', 'X']
>>> y5
['P', 'L']
你可以随机播放列表的副本(你说你想重用这么一个需要做出一个副本,因为就地洗牌作品),然后只需要2元每个样品:
import random
x_copy = x[:] # copy
random.shuffle(x_copy)
y1 = x[:2]
y2 = x[2:4]
y3 = x[4:6]
y4 = x[6:8]
y5 = x[8:10]
,或者你不想硬编码yi
S:
x_copy = x[:] # copy
random.shuffle(x_copy)
y = [x_copy[i*2: (i+1)*2] for i in range(5)]
print(y)
# [['W', 'Z'], ['A', 'Q'], ['B', 'J'], ['O', 'D'], ['X', 'E']]
你也可以遍历中产生的采样和移除x
的元素:
x = ['A','B','C','D','E','F',
'G','H','I','J','K','L',
'M','N','O','P','Q','R',
'S','T','U','V','W','X',
'Y','Z']
new_x = x[:]
import random
final_list = []
for i in range(5):
the_sample = random.sample(new_x, 2)
final_list.append(the_sample)
for b in the_sample:
new_x.remove(b)
输出:
[['C', 'R'], ['L', 'V'], ['W', 'Y'], ['D', 'O'], ['J', 'Q']]
谢谢!虽然'我希望能够实现这一点,而不必从列表中删除项目,因为它稍后会在代码中重用。' – LearningToPython
为什么downvote? – Ajax1234
您可以使用numpy.random.choice
。其目的是(replace=True
)选择或不(replace=False
)从阵列状物体替代(也适用于您的列表):
import numpy as np
x = ['A','B','C','D','E','F',
'G','H','I','J','K','L',
'M','N','O','P','Q','R',
'S','T','U','V','W','X',
'Y','Z']
np.random.choice(x, size=(5, 2), replace=False)
结果:
array([['Y', 'Q'],
['W', 'R'],
['O', 'H'],
['Z', 'G'],
['L', 'M']],
dtype='<U1')
这将返回数组5行,其中每个包括您大小的样品之一2.
你可以简单地建立一个生成的值的“缓存” - 这样的x
的元素是不能删除:
import random
class SampleCache():
x = ['A','B','C','D','E','F',
'G','H','I','J','K','L',
'M','N','O','P','Q','R',
'S','T','U','V','W','X',
'Y','Z']
def __init__(self):
self.cache = []
def get(self):
_iterations = 0
while 1:
sample = random.sample(self.x, 2)
if not sample in self.cache:
self.cache.append(sample)
return sample
if _iterations > 1000: # just to prevent NOT to run into an infinite loop
break
s = SampleCache()
for x in range(25):
print(s.get())
使用random.sample
来生成初始列表的混洗副本以及根据需要产生混洗值的生成器。
def random_sample(x, n):
shuffled = random.sample(x, k=len(x))
for val in range(0, len(x), n):
yield shuffled[val: val+n]
print([sample for sample in random_sample(x, 2)])
输出;
[['I', 'O'], ['V', 'T'], ['U', 'J'], ['L', 'A'],
['E', 'G'], ['Q', 'F'], ['M', 'H'], ['B', 'K'],
['R', 'P'], ['W', 'N'], ['D', 'S'], ['Z', 'Y'],
['X', 'C']]
如果你想正好五个随机值,然后利用这一点;
samples = random_sample(x, 2)
five_samples = [next(samples) for _ in range(5)]
print(five_samples)
如果想让他们一次一个,然后使用,
samples = random_sample(x, 2)
print(next(samples))
...
print(next(samples))
random.sample
是正确的方法,你只需要使用2个字母调用一次为10个字母,而不是5次:
import random
import string
def random_letters(m=5, n=2):
letters = random.sample(string.ascii_uppercase, m * n)
return [letters[n * i:n * (i + 1)] for i in range(m)]
print(random_letters())
# [['I', 'X'], ['J', 'U'], ['O', 'W'], ['G', 'C'], ['D', 'F']]
print(random_letters())
# [['J', 'X'], ['N', 'P'], ['A', 'C'], ['O', 'Z'], ['B', 'H']]
print(random_letters())
# [['U', 'T'], ['J', 'N'], ['C', 'H'], ['D', 'I'], ['K', 'P']]
print(random_letters())
# [['U', 'G'], ['L', 'V'], ['A', 'R'], ['J', 'F'], ['S', 'C']]
print(random_letters())
# [['Y', 'C'], ['R', 'B'], ['E', 'I'], ['S', 'T'], ['H', 'X']]
这很完美!谢谢。我不特别这个部分:'[我* 2:(i + 1)* 2]'。介意澄清? ;) – LearningToPython
你的意思是列表理解还是'x_copy [i * 2:(i + 1)* 2]'部分? – MSeifert
是的,一点点;/- 你提到的'部分'; – LearningToPython