我一直在嘗試創建 15 個數字的隨機串列,從每個可用串列(15 個串列)中只選擇一個,并且不重復任何數字。
下面的代碼做到了這一點,但僅限于兩個不同的串列。我想擺脫這個限制。
import random
n1 = list(range(1, 5))
n2 = list(range(2, 5))
n3 = list(range(3,6))
n4 = list(range(5,8))
n5 = list(range(6,10))
n6 = list(range(8,12))
n7 = list(range(10,13))
n8 = list(range(11,15))
n9 = list(range(13,17))
n10 = list(range(14,18))
n11 = list(range(16,20))
n12 = list(range(18,21))
n13 = list(range(20,23))
n14 = list(range(22,24))
n15 = list(range(23,25))
for i in range(10):
lista = random.sample(list(zip(n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15)),1)
print(lista)
uj5u.com熱心網友回復:
當你做類似的事情時
zip([1,2,3,4],[5,6,7,8])
結果輸出只是對
[(1, 5), (2, 6), (3, 7), (4, 8)]
所以你沒有得到像 (1, 6) 或 (2, 5) 這樣的東西作為可能的選項。如果你真的想做這樣的事情,你應該做一個笛卡爾積,像這樣:
itertools.product([1,2,3,4],[5,6,7,8])
這將為您提供所有可能的組合。例如:
>>> random.choice(list(itertools.product([1,2,3,4],[5,6,7,8])))
(1, 6)
但是,如果您實際上嘗試使用其中包含一個或兩個以上元素的集合的 15 路笛卡爾積,那么它將構建的結果集合將是巨大的,并且可能不適合記憶體。
此外,如果集合重疊,您必須通過并進行某種過濾以丟棄多次選擇相同數字的選項。
獲得沒有重復的隨機串列并且從集合中選擇每個元素的最簡單方法就是逐個元素選擇:
def pick_unique_elements_from_lists(*args):
while True:
result = []
already_chosen = set()
for arg in args:
valid_choices = [ n for n in arg if n not in already_chosen ]
if not valid_choices:
continue
choice = random.choice(valid_choices)
result.append(choice)
already_chosen.add(choice)
return tuple(result)
然而,雖然這里的選擇是隨機的,但我們可能想知道它們是否會是一律隨機的。例如,假設我們要選擇一個 4 元組,第一個元素來自 [1,2],第二個來自 [1,3],第三個來自 [1,4],第四個來自 [1, 5]。有幾種方法可以做到這一點:
- (1, 3, 4, 5)
- (2, 1, 4, 5)
- (2, 3, 1, 5)
- (2, 3, 4, 1)
- (2, 3, 4, 5)
因此,如果我們隨機均勻地采樣,我們預計元組的第一個元素大約有 80% 的時間是 2。然而,這不是pick_unique_elements_from_lists函式的作用;如果你嘗試一下,你會發現它在大約 50% 的情況下為你提供了以 1 開頭的元組。
該函式還有另一個缺點pick_unique_elements_from_lists,如果你給它一個引數序列,就不可能從中選擇任何不同元素的元組,例如
[1, 2], [2, 3], [1, 3]
然后它將永遠旋轉,試圖提出一個有效的樣本。
如果您需要統一采樣,我可以看到三種方法:
- 實際上列舉您可以獲得的每個可能的元組,然后隨機選擇其中一個。
- 接受/拒絕對整個數字世界的隨機序列進行抽樣。這在有界空間中運行,但可能需要很長時間。
- 想出一個聰明的有效樣本雙射列舉,并用它來構造一個干凈的采樣演算法。我不知道這會有多難,盡管我警告你,聽起來像這樣的問題通常非常困難。
這是一個如何執行接受/拒絕方法的示例:
def accept_reject_from_lists(*args):
universe = set().union(*args)
found = False
while not found:
candidate = random.sample(universe, len(args))
found = True
for i in range(len(candidate)):
if candidate[i] not in args[i]:
found = False
break
return tuple(candidate)
這仍然有一個缺點,如果沒有任何元組滿足您的條件,它將進入無限回圈,并且根據您的串列之間有多少重疊,它也可能需要很長時間,但從好的方面來說,它不會如果您給它一個巨大的問題要解決,就不會耗盡記憶體并崩潰。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/515912.html
標籤:Python列表随机的
上一篇:使用lapply創建矩陣
下一篇:如何使用串列創建具有多個值的字典
