2017-07-18 92 views
4

代碼:隨機從列表中選擇一個不同的對項

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'] 

回答

4

你可以隨機播放列表的副本(你說你想重用這麼一個需要做出一個副本,因爲就地洗牌作品),然後只需要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']] 
+0

這很完美!謝謝。我不特別這個部分:'[我* 2:(i + 1)* 2]'。介意澄清? ;) – LearningToPython

+0

你的意思是列表理解還是'x_copy [i * 2:(i + 1)* 2]'部分? – MSeifert

+0

是的,一點點;/- 你提到的'部分'; – LearningToPython

-1

你也可以遍歷中產生的採樣和移除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']] 
+0

謝謝!雖然'我希望能夠實現這一點,而不必從列表中刪除項目,因爲它稍後會在代碼中重用。' – LearningToPython

+0

爲什麼downvote? – Ajax1234

2

您可以使用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.

1

你可以簡單地建立一個生成的值的「緩存」 - 這樣的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()) 
0

使用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)) 
1

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']] 
相關問題