İşte Python'dan @Derek tarafından taşınan kodun optimize edilmiş bir sürümü , eklenmiş yıkıcı (yerinde) seçenekle birlikte gidebilirseniz mümkün olan en hızlı algoritma olmasını sağlar. Aksi takdirde ya tam bir kopya oluşturur ya da büyük bir diziden istenen az sayıda öğe için seçim tabanlı bir algoritmaya geçer.
function sample(pool, k, destructive) {
var n = pool.length;
if (k < 0 || k > n)
throw new RangeError("Sample larger than population or is negative");
if (destructive || n <= (k <= 5 ? 21 : 21 + Math.pow(4, Math.ceil(Math.log(k*3, 4))))) {
if (!destructive)
pool = Array.prototype.slice.call(pool);
for (var i = 0; i < k; i++) {
var j = i + Math.random() * (n - i) | 0;
var x = pool[i];
pool[i] = pool[j];
pool[j] = x;
}
pool.length = k;
return pool;
} else {
var selected = new Set();
while (selected.add(Math.random() * n | 0).size < k) {}
return Array.prototype.map.call(selected, i => population[i]);
}
}
Derek'in uygulamasına kıyasla, ilk algoritma Firefox'ta çok daha hızlı, Chrome'da biraz daha yavaş, ancak şimdi yıkıcı seçeneğe sahip - en performanslı olanı. İkinci algoritma sadece% 5-15 daha hızlıdır. K ve n'ye bağlı olarak değiştikleri ve muhtemelen yeni tarayıcı sürümleriyle gelecekte bir şey ifade etmeyecekleri için somut sayılar vermemeye çalışıyorum.
Algoritmalar arasında seçim yapan sezgisel yöntem, Python kodundan kaynaklanır. Bazen daha yavaş olanı seçmesine rağmen, olduğu gibi bıraktım. JS için optimize edilmelidir, ancak köşe kasaların performansı tarayıcıya ve sürümlerine bağlı olduğundan karmaşık bir görevdir. Örneğin 1000 veya 1050 üzerinden 20'yi seçmeye çalıştığınızda, buna göre birinci veya ikinci algoritmaya geçecektir. Bu durumda, ilki Chrome 80'de ikinciden 2 kat daha hızlı, Firefox 74'te ise 3 kat daha yavaş çalışır.