我想在一個只包含 0 和 1 的一維陣列中隨機交換一個0和一個1,很多次說最多N = 10^6。這是我進行一次交換的代碼。
import numpy as np
# a contains only 0 and 1
a = np.array([0,1,1,0,1,1,0,0,0,1])
# j1 random position of 0, j2 random position of 1
j1 = np.random.choice(np.where(a==0)[0])
j2 = np.random.choice(np.where(a==1)[0])
# swap
a[j1], a[j2] = a[j2], a[j1]
由于我想多次執行此程序,因此在每次迭代中,我都需要使用 np.where() 來定位 0 和 1 的位置,我認為這不是那么有效。
還有其他更有效的方法嗎?
uj5u.com熱心網友回復:
在執行交換時,您可以自己維護where運算式的結果,這樣您就不需要重新執行該where呼叫。您只需在程式開始時執行一次,但隨后在回圈中,您將逐步調整。
此外,交換可以用兩個賦值替換,因為您知道 0 將變為 1,反之亦然。
a = np.array([0,1,1,0,1,1,0,0,0,1])
# One-time preprocessing
zeroes = np.where(a==0)[0]
ones = np.where(a==1)[0]
num_zeroes = len(zeroes)
num_ones = len(ones)
# In a loop:
for _ in range(100):
# Choose random indices in zeroes/ones
j0 = np.random.randint(num_zeroes)
j1 = np.random.randint(num_ones)
# Get the chosen indices for use in `a`:
i0 = zeroes[j0]
i1 = ones[j1]
# Keep the two collections in sync with the swap that now happens
zeroes[j0] = i1
ones[j1] = i0
# The swap itself
a[i0] = 1
a[i1] = 0
# ...
請注意 和 的長度zeroes不會ones改變:我們可以重復使用在每次交換時選擇的兩個插槽。
uj5u.com熱心網友回復:
我想放棄我在評論中描述的內容作為答案,前提是該陣列有點接近 0 和 1 的 50:50 分布。
這種方法的優點是,雖然不是在固定的執行時間上,但與陣列大小有關的時間復雜度為 O(1),因此對于較大的陣列,它可以輕松擊敗 trincots 方法。
length = 1e8
a = (np.random.randint(0,2,int(length))).astype(np.uint8)
t = time.time_ns()
rng = np.random.default_rng()
for i in range(10000):
b = rng.integers(0, length)
while(True):
c = rng.integers(0, length)
if c == b:
continue
if a[c] != a[b]:
a[c] ^= 1
break
a[b] ^= 1
print((time.time_ns()-t)/1e9)
# Trincot
t = time.time_ns()
zeroes = np.where(a==0)[0]
ones = np.where(a==1)[0]
num_zeroes = len(zeroes)
num_ones = len(ones)
for _ in range(10000):
# Choose random indices in zeroes/ones
j0 = np.random.randint(num_zeroes)
j1 = np.random.randint(num_ones)
# Get the chosen indices:
i0 = zeroes[j0]
i1 = ones[j1]
# Keep the two collections in sync with the swap that now happens
zeroes[j0] = i1
ones[j1] = i0
# The swap itself
a[i0] = 1
a[i1] = 0
print((time.time_ns()-t)/1e9)
結果:
0.1360712
1.3667251
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/488626.html
