I am working on 'how to access elements randomly from an array in javascript'. I found many links regarding this. Like: Get random item from JavaScript array
我正在研究“如何从javascript数组中随机访问元素”。我发现了很多关于这个的链接。例如:从JavaScript数组中获取随机项
var item = items[Math.floor(Math.random()*items.length)];
Question: But in this we can choose only one item from the array.If we want more than one elements then how can we achieve this.So please just from this statement how can we get more than one elements from an array.
问题:但是在这里我们只能从数组中选择一项。如果我们想要一个以上的要素,那么我们怎样才能做到这一点呢?请从这个语句中我们如何从数组中获得多个元素。
9 个解决方案
#1
30
Try this non-destructive (and fast) function:
尝试这个无损(和快速)功能:
function getRandom(arr, n) {
var result = new Array(n),
len = arr.length,
taken = new Array(len);
if (n > len)
throw new RangeError("getRandom: more elements taken than available");
while (n--) {
var x = Math.floor(Math.random() * len);
result[n] = arr[x in taken ? taken[x] : x];
taken[x] = --len in taken ? taken[len] : len;
}
return result;
}
#2
35
Just two lines :
只是两行:
const shuffled = array.sort(() => .5 - Math.random());// shuffle
let selected =shuffled.slice(0,n) ; //get sub-array of first n elements AFTER shuffle
DEMO :
#3
8
create a funcion which does that:
创建一个函数
var getMeRandomElements = function(sourceArray, neededElements) {
var result = [];
for (var i = 0; i < neededElements; i++) {
result.push(sourceArray[Math.floor(Math.random()*sourceArray.length)]);
}
return result;
}
you should also check if the sourceArray has enough elements to be returned. and if you want unique elements returned, you should remove selected element from the sourceArray.
您还应该检查sourceArray是否有足够的元素要返回。如果您希望返回唯一的元素,您应该从sourceArray中删除所选的元素。
#4
3
Porting .sample
from the Python standard library:
从Python标准库中移植.sample:
function sample(population, k){
/*
Chooses k unique random elements from a population sequence or set.
Returns a new list containing elements from the population while
leaving the original population unchanged. The resulting list is
in selection order so that all sub-slices will also be valid random
samples. This allows raffle winners (the sample) to be partitioned
into grand prize and second place winners (the subslices).
Members of the population need not be hashable or unique. If the
population contains repeats, then each occurrence is a possible
selection in the sample.
To choose a sample in a range of integers, use range as an argument.
This is especially fast and space efficient for sampling from a
large population: sample(range(10000000), 60)
Sampling without replacement entails tracking either potential
selections (the pool) in a list or previous selections in a set.
When the number of selections is small compared to the
population, then tracking selections is efficient, requiring
only a small set and an occasional reselection. For
a larger number of selections, the pool tracking method is
preferred since the list takes less space than the
set and it doesn't suffer from frequent reselections.
*/
if(!Array.isArray(population))
throw new TypeError("Population must be an array.");
var n = population.length;
if(k < 0 || k > n)
throw new RangeError("Sample larger than population or is negative");
var result = new Array(k);
var setsize = 21; // size of a small set minus size of an empty list
if(k > 5)
setsize += Math.pow(4, Math.ceil(Math.log(k * 3, 4)))
if(n <= setsize){
// An n-length list is smaller than a k-length set
var pool = population.slice();
for(var i = 0; i < k; i++){ // invariant: non-selected at [0,n-i)
var j = Math.random() * (n - i) | 0;
result[i] = pool[j];
pool[j] = pool[n - i - 1]; // move non-selected item into vacancy
}
}else{
var selected = new Set();
for(var i = 0; i < k; i++){
var j = Math.random() * (n - i) | 0;
while(selected.has(j)){
j = Math.random() * (n - i) | 0;
}
selected.add(j);
result[i] = population[j];
}
}
return result;
}
Implementation ported from Lib/random.py.
实现从Lib / random.py移植。
Notes:
注:
-
setsize
is set based on characteristics in Python for efficiency. Although it has not been adjusted for JavaScript, the algorithm will still function as expected. - setsize是根据Python的特性设置的,以提高效率。虽然还没有对JavaScript进行调整,但是该算法仍然可以正常工作。
- Some other answers described in this page are not safe according to the ECMAScript specification due to the misuse of
Array.prototype.sort
. This algorithm however is guaranteed to terminate in finite time. - 根据ECMAScript规范,由于Array.prototype.sort的误用,本页面中描述的其他一些答案并不安全。但是,该算法保证在有限的时间内终止。
- For older browsers that do not have
Set
implemented, the set can be replaced with anArray
and.has(j)
replaced with.indexOf(j) > -1
. - 对于没有实现Set的旧浏览器,可以用数组替换Set,用. indexof (j) > -1替换。
Performance against the accepted answer:
对公认答案的性能:
- https://jsperf.com/pick-random-elements-from-an-array
- https://jsperf.com/pick-random-elements-from-an-array
- The performance difference is the greatest on Safari.
- 在Safari浏览器上,性能差异最大。
#5
2
Array.prototype.getnkill = function() {
var a = Math.floor(Math.random()*this.length);
var dead = this[a];
this.splice(a,1);
return dead;
}
//.getnkill() removes element in the array
//so if you like you can keep a copy of the array first:
//var original= items.slice(0);
var item = items.getnkill();
var anotheritem = items.getnkill();
#6
1
If you want to randomly get items from the array in a loop without repetitions you need to remove the selected item from the array with splice
:
如果要在循环中随机地从数组中获取项而不重复,则需要使用splice从数组中删除所选项:
var items = [1, 2, 3, 4, 5];
var newItems = [];
for(var i = 0; i < 3; i++) {
var idx = Math.floor(Math.random() * items.length);
newItems.push(items[idx]);
items.splice(idx, 1);
}
例如小提琴
#7
1
EDIT: This solution is slower than others presented here (which splice the source array) if you want to get only a few elements. The speed of this solution depends only on the number of elements in the original array, while the speed of the splicing solution depends on the number of elements required in the output array.
编辑:如果你只想得到一些元素,这个解决方案比这里的其他解决方案要慢一些(它可以拼接源数组)。该解决方案的速度仅取决于原始数组中的元素数量,而拼接解决方案的速度取决于输出数组中所需的元素数量。
If you want non-repeating random elements, you can shuffle your array then get only as many as you want:
如果你想要不重复的随机元素,你可以洗牌你的数组,然后只得到你想要的数量:
function shuffle(array) {
var counter = array.length, temp, index;
// While there are elements in the array
while (counter--) {
// Pick a random index
index = (Math.random() * counter) | 0;
// And swap the last element with it
temp = array[counter];
array[counter] = array[index];
array[index] = temp;
}
return array;
}
var arr = [0,1,2,3,4,5,7,8,9];
var randoms = shuffle(arr.slice(0)); // array is cloned so it won't be destroyed
randoms.length = 4; // get 4 random elements
DEMO: http://jsbin.com/UHUHuqi/1/edit
演示:http://jsbin.com/UHUHuqi/1/edit
Shuffle function taken from here: https://*.com/a/6274398/1669279
洗牌函数:https://*.com/a/6274398/1669279
#8
1
Getting 5 random items without changing the original array:
得到5个随机项目,不改变原始数组:
const n = 5;
const sample = items
.map(x => ({ x, r: Math.random() }))
.sort((a, b) => a.r - b.r)
.map(a => a.x)
.slice(0, n);
#9
-1
Here is the most correct answer and it will give you Random + Unique elements.
这是最正确的答案,它会给你随机+唯一的元素。
function randomize(array, n)
{
var final = [];
array = array.filter(function(elem, index, self) {
return index == self.indexOf(elem);
}).sort(function() { return 0.5 - Math.random() });
var len = array.length,
n = n > len ? len : n;
for(var i = 0; i < n; i ++)
{
final[i] = array[i];
}
return final;
}
// randomize([1,2,3,4,5,3,2], 4);
// Result: [1, 2, 3, 5] // Something like this
#1
30
Try this non-destructive (and fast) function:
尝试这个无损(和快速)功能:
function getRandom(arr, n) {
var result = new Array(n),
len = arr.length,
taken = new Array(len);
if (n > len)
throw new RangeError("getRandom: more elements taken than available");
while (n--) {
var x = Math.floor(Math.random() * len);
result[n] = arr[x in taken ? taken[x] : x];
taken[x] = --len in taken ? taken[len] : len;
}
return result;
}
#2
35
Just two lines :
只是两行:
const shuffled = array.sort(() => .5 - Math.random());// shuffle
let selected =shuffled.slice(0,n) ; //get sub-array of first n elements AFTER shuffle
DEMO :
#3
8
create a funcion which does that:
创建一个函数
var getMeRandomElements = function(sourceArray, neededElements) {
var result = [];
for (var i = 0; i < neededElements; i++) {
result.push(sourceArray[Math.floor(Math.random()*sourceArray.length)]);
}
return result;
}
you should also check if the sourceArray has enough elements to be returned. and if you want unique elements returned, you should remove selected element from the sourceArray.
您还应该检查sourceArray是否有足够的元素要返回。如果您希望返回唯一的元素,您应该从sourceArray中删除所选的元素。
#4
3
Porting .sample
from the Python standard library:
从Python标准库中移植.sample:
function sample(population, k){
/*
Chooses k unique random elements from a population sequence or set.
Returns a new list containing elements from the population while
leaving the original population unchanged. The resulting list is
in selection order so that all sub-slices will also be valid random
samples. This allows raffle winners (the sample) to be partitioned
into grand prize and second place winners (the subslices).
Members of the population need not be hashable or unique. If the
population contains repeats, then each occurrence is a possible
selection in the sample.
To choose a sample in a range of integers, use range as an argument.
This is especially fast and space efficient for sampling from a
large population: sample(range(10000000), 60)
Sampling without replacement entails tracking either potential
selections (the pool) in a list or previous selections in a set.
When the number of selections is small compared to the
population, then tracking selections is efficient, requiring
only a small set and an occasional reselection. For
a larger number of selections, the pool tracking method is
preferred since the list takes less space than the
set and it doesn't suffer from frequent reselections.
*/
if(!Array.isArray(population))
throw new TypeError("Population must be an array.");
var n = population.length;
if(k < 0 || k > n)
throw new RangeError("Sample larger than population or is negative");
var result = new Array(k);
var setsize = 21; // size of a small set minus size of an empty list
if(k > 5)
setsize += Math.pow(4, Math.ceil(Math.log(k * 3, 4)))
if(n <= setsize){
// An n-length list is smaller than a k-length set
var pool = population.slice();
for(var i = 0; i < k; i++){ // invariant: non-selected at [0,n-i)
var j = Math.random() * (n - i) | 0;
result[i] = pool[j];
pool[j] = pool[n - i - 1]; // move non-selected item into vacancy
}
}else{
var selected = new Set();
for(var i = 0; i < k; i++){
var j = Math.random() * (n - i) | 0;
while(selected.has(j)){
j = Math.random() * (n - i) | 0;
}
selected.add(j);
result[i] = population[j];
}
}
return result;
}
Implementation ported from Lib/random.py.
实现从Lib / random.py移植。
Notes:
注:
-
setsize
is set based on characteristics in Python for efficiency. Although it has not been adjusted for JavaScript, the algorithm will still function as expected. - setsize是根据Python的特性设置的,以提高效率。虽然还没有对JavaScript进行调整,但是该算法仍然可以正常工作。
- Some other answers described in this page are not safe according to the ECMAScript specification due to the misuse of
Array.prototype.sort
. This algorithm however is guaranteed to terminate in finite time. - 根据ECMAScript规范,由于Array.prototype.sort的误用,本页面中描述的其他一些答案并不安全。但是,该算法保证在有限的时间内终止。
- For older browsers that do not have
Set
implemented, the set can be replaced with anArray
and.has(j)
replaced with.indexOf(j) > -1
. - 对于没有实现Set的旧浏览器,可以用数组替换Set,用. indexof (j) > -1替换。
Performance against the accepted answer:
对公认答案的性能:
- https://jsperf.com/pick-random-elements-from-an-array
- https://jsperf.com/pick-random-elements-from-an-array
- The performance difference is the greatest on Safari.
- 在Safari浏览器上,性能差异最大。
#5
2
Array.prototype.getnkill = function() {
var a = Math.floor(Math.random()*this.length);
var dead = this[a];
this.splice(a,1);
return dead;
}
//.getnkill() removes element in the array
//so if you like you can keep a copy of the array first:
//var original= items.slice(0);
var item = items.getnkill();
var anotheritem = items.getnkill();
#6
1
If you want to randomly get items from the array in a loop without repetitions you need to remove the selected item from the array with splice
:
如果要在循环中随机地从数组中获取项而不重复,则需要使用splice从数组中删除所选项:
var items = [1, 2, 3, 4, 5];
var newItems = [];
for(var i = 0; i < 3; i++) {
var idx = Math.floor(Math.random() * items.length);
newItems.push(items[idx]);
items.splice(idx, 1);
}
例如小提琴
#7
1
EDIT: This solution is slower than others presented here (which splice the source array) if you want to get only a few elements. The speed of this solution depends only on the number of elements in the original array, while the speed of the splicing solution depends on the number of elements required in the output array.
编辑:如果你只想得到一些元素,这个解决方案比这里的其他解决方案要慢一些(它可以拼接源数组)。该解决方案的速度仅取决于原始数组中的元素数量,而拼接解决方案的速度取决于输出数组中所需的元素数量。
If you want non-repeating random elements, you can shuffle your array then get only as many as you want:
如果你想要不重复的随机元素,你可以洗牌你的数组,然后只得到你想要的数量:
function shuffle(array) {
var counter = array.length, temp, index;
// While there are elements in the array
while (counter--) {
// Pick a random index
index = (Math.random() * counter) | 0;
// And swap the last element with it
temp = array[counter];
array[counter] = array[index];
array[index] = temp;
}
return array;
}
var arr = [0,1,2,3,4,5,7,8,9];
var randoms = shuffle(arr.slice(0)); // array is cloned so it won't be destroyed
randoms.length = 4; // get 4 random elements
DEMO: http://jsbin.com/UHUHuqi/1/edit
演示:http://jsbin.com/UHUHuqi/1/edit
Shuffle function taken from here: https://*.com/a/6274398/1669279
洗牌函数:https://*.com/a/6274398/1669279
#8
1
Getting 5 random items without changing the original array:
得到5个随机项目,不改变原始数组:
const n = 5;
const sample = items
.map(x => ({ x, r: Math.random() }))
.sort((a, b) => a.r - b.r)
.map(a => a.x)
.slice(0, n);
#9
-1
Here is the most correct answer and it will give you Random + Unique elements.
这是最正确的答案,它会给你随机+唯一的元素。
function randomize(array, n)
{
var final = [];
array = array.filter(function(elem, index, self) {
return index == self.indexOf(elem);
}).sort(function() { return 0.5 - Math.random() });
var len = array.length,
n = n > len ? len : n;
for(var i = 0; i < n; i ++)
{
final[i] = array[i];
}
return final;
}
// randomize([1,2,3,4,5,3,2], 4);
// Result: [1, 2, 3, 5] // Something like this