我想知道如何random.sample()在 -loop 中使用 python 函式for來生成多個不相同的示例串列。
例如,現在我有:
for i in range(3):
sample = random.sample(range(10), k=2)
這將生成 3 個樣本串列,每個串列包含兩個數字,但我想確保這些樣本串列都不相同。(如果有重復值也可以,即 , ,(2,1)可以,但是, ,不行。)(3,2)(3,7)(2,1)(1,2)(5,4)
uj5u.com熱心網友回復:
如果您特別需要“random.sample()在 for 回圈中使用”,那么您可以跟蹤sample您已經看到的 s,并檢查尚未看到新的。
import random
seen = set()
for i in range(3):
while True:
sample = random.sample(range(10), k=2)
print(f'TESTING: {sample = }') # For demo
fr = frozenset(sample)
if fr not in seen:
seen.add(fr)
break
print(sample)
示例輸出:
TESTING: sample = [0, 7]
[0, 7]
TESTING: sample = [0, 7]
TESTING: sample = [1, 5]
[1, 5]
TESTING: sample = [7, 0]
TESTING: sample = [3, 5]
[3, 5]
在這里,我做seen了 aset以允許快速查找,并且我轉換sample為 afrozenset以便在比較中順序無關緊要。它必須被凍結,因為 aset不能包含另一個set。
但是,對于不同的輸入,這可能會非常慢,尤其是從更大范圍i或更小的范圍中抽取樣本。理論上,它的運行時間是無限的,但實際上,它random的數字生成器是有限的。
備擇方案
還有其他方法可以做同樣的事情,可能會更好。例如,您可以隨機抽取一個大樣本,然后將其分塊為所需的大小:
n = 3
k = 2
upper = 10
sample = random.sample(range(upper), k=k*n)
for chunk in chunks(sample, k):
print(chunk)
示例輸出:
[6, 5]
[3, 0]
[1, 8]
使用這種方法,您將永遠不會得到任何重復[[2,1], [3,2], [3,7]]的數字,因為樣本包含所有唯一的數字。
這種方法的靈感來自Sven Marnach 關于“Non-repetitive random number in numpy”的回答,我碰巧今天剛剛讀到。
uj5u.com熱心網友回復:
看起來您正在嘗試制作某些串列項的嵌套串列而不重復原始串列,您可以嘗試以下代碼。
import random
mylist = list(range(50))
def randomlist(mylist,k):
length = lambda : len(mylist)
newlist = []
while length() >= k:
newlist.append([mylist.pop(random.randint(0, length() - 1)) for I in range(k)])
newlist.append(mylist)
return newlist
randomlist(mylist,6)
[[2, 20, 36, 46, 14, 30],
[4, 12, 13, 3, 28, 5],
[45, 37, 18, 9, 34, 24],
[31, 48, 11, 6, 19, 17],
[40, 38, 0, 7, 22, 42],
[23, 25, 47, 41, 16, 39],
[8, 33, 10, 43, 15, 26],
[1, 49, 35, 44, 27, 21],
[29, 32]]
uj5u.com熱心網友回復:
這應該可以解決問題。
import random
import math
# create set to store samples
a = set()
# number of distinct elements in the population
m = 10
# sample size
k = 2
# number of samples
n = 3
# this protects against an infinite loop (see Safety Note)
if n > math.comb(m, k):
print(
f"Error: {math.comb(m, k)} is the number of {k}-combinations "
f"from a set of {m} distinct elements."
)
exit()
# the meat
while len(a) < n:
a.add(tuple(sorted(random.sample(range(m), k = k))))
print(a)
使用 aset您可以保證獲得一個沒有重復元素的集合。在一個集合中,您將被允許擁有(1, 2)和(2, 1)在里面,這就是sorted應用的原因。因此,如果[1, 2]繪制,則sorted([1, 2])回傳[1, 2]。如果[2, 1]隨后繪制,則sorted([2, 1])回傳[1, 2],它不會被添加到集合中,因為(1, 2)它已經在集合中。我們使用tuple是因為 a 中的物件set必須是可散列的,而list物件不是。
我希望這有幫助。有任何問題,請告訴我。
安全注意事項
為避免將 3 更改為某個大數時出現無限回圈,您需要知道所需型別的可能樣本的最大數量。
與此相關的數學概念是一個組合。
- 假設您的第一個引數是
random.sample()某個任意正整數。請注意,這意味著樣本將來自不同成員的群體,無需替換。range(m)mm - 假設您希望獲得總
n長度k的樣本。
來自不同元素k集合的可能組合的數量是m
米!/ (k! * (m - k)!)
您可以通過以下方式獲取此值
from math import comb
num_comb = comb(m, k)
comb(m, k)給出了從元素中選擇k元素的不同方法的數量,m沒有重復和沒有順序,這正是我們想要的。
所以在上面的例子中,m = 10, k = 2, n = 3.
With these m and k, the number of possible k-combinations from the set of m distinct elements is 45.
You need to ensure that n is less than 45 if you want to use those specific m and k and avoid an infinite loop.
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/456884.html
下一篇:用流替換通常的for回圈
