2016-04-24 146 views
1

我有一个数组Javascript - 如何从数组中随机挑选元素?

var numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18"]; 

,并试图从中获得随机物品,所以:

console.log(_.sample(numbers, 5)); 

这会给我从阵列5张随机数(串)按随机顺序,像:

"17", "2", "3", "18", "10" 

如何获得排序列表或随机项目?

"2", "3", "10", "17", "18" 

_.sample可能不是这里的最佳选择。我试图从给定数组中获取随机项目,并将这些项目从数组的左侧移到右侧。

如何在javascritp中做到这一点?

谢谢。

编辑:我有一个字符串数组,而不是数字,所以我无法排序随机选取的项目。

EDIT2:为了避免混淆,在数组中使用单词(=字符串),我使用数字作为字符串来更容易地展示我试图实现的内容。 (对不起,可能混淆)

+0

字符串可以很容易地也可以按数字排序。或者数字串只是一个例子? – nnnnnn

+0

在上面的例子中,我使用了数字,因为我想要做的更简单的演示 - 在数组中是字符串(单词)。 – user984621

回答

3

您可以使用Array.prototype.sort到返回数组排序:

即。

_.sample(numbers, 5).sort(function(a, b) { return parseInt(a, 10) - parseInt(b, 10) }) 

一个更好的随机是:

var randomChoice = numbers[~~(Math.random() * numbers.length)] 

:在~~执行在这种情况下同样的动作为Math.floor()。它们可以互换。

一起:

var numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18"]; 

var randomSample = [] 

for(var i=0; i < 5; i++) { 
    var randomChoice = numbers[~~(Math.random() * numbers.length)] 
    randomSample.push(randomChoice) 
} 

var sortedRandomSample = randomSample.sort(function(a, b) { return parseInt(a, 10) - parseInt(b, 10) }) 

演示:https://jsbin.com/zosizefaga/edit?html,js,console,output

+0

for循环可能会选取相同元素五次。 – nnnnnn

+0

你说得对。这就是随机选择的本质。 @nnnnnn。 – agconti

+0

但这不是OP想要的。他们显然需要随机选择五个不同的元素。 – nnnnnn

0

你为什么不实现自己的样品,并呼吁_.sample你调用该方法排序后的方法?

+1

这似乎更像是一个评论而不是一个答案。 –

1

这是一个解决方案,不会对原始订单做任何假设。这个想法是查找元素在原始数组中的位置并按此排序。但是,这假定每个元素都是唯一的。

sample.sort(function(a, b) { 
    return numbers.indexOf(a) - numbers.indexOf(b); 
}); 

这对于大型阵列来说也会很慢。

+0

我认为复杂性是O(n 2 log n)。如果你想改进它,你可以创建一个使用字符串作为键和索引作为值的散列。如果在排序之前执行此操作并使用散列而不是“indexOf”,则会再次使其成为O(n log n)。 – kamoroso94

0

试试这个:

function random(array, elements) { 
    return array.concat().sort(function() { 
    if (Math.random() < 0.5) { 
     return -1; 
    } else { 
     return 1; 
    } 
    }).slice(0, elements).sort(
    function(a, b) { 
     return a - b 
    }); 
} 

这里的小提琴:

JSFiddle

+1

但是...这会修改原始数组,并以随机顺序返回所选元素。 OP不想做这些事情之一。 – nnnnnn

+0

它不会修改原始数组,请检查小提琴。是的,它是返回一个随机排列数组,我的错误。 – Gerardo

+0

它*修改原始数组。添加'console.log(数字);'*之后*你调用你的函数,你会看到。 – nnnnnn

0

我能想到的是如下的最简单的方法:

var randomSample = _.sample(numbers.map(function(v,i){ return i; }), 5) 
        .sort(function(a,b){ return a-b; }) 
        .map(function(v){ return numbers[v]; }); 

也就是说,使临时数组,保存原始数组的索引,即,只是数字0通过numbers.length - 1):

var indices = numbers.map(function(v,i){ return i; }) 

采取随机样本而数组:

var sampleIndices = _.sample(indices, 5) 

排序样品:

sampleIndices.sort(function(a,b){ return a-b; }) 

然后使用排序,随机选择的索引以从原始数组中获取数值:

var randomSample = sampleIndices.map(function(v){ return numbers[v]; }); 

而且如我的答案开头所示,您可以在一行中完成所有操作,而无需使用indicessampleIndices变量。尽管如果你打算经常从同一个numbers阵列中取样,那么保留indices变量以保存每次重建都可能是有意义的,尤其是当原始阵列非常大时。

无论原始数组中的值是什么类型,这都会起作用,因为一旦选择了随机索引,那些值就在最后选出。

0

这是一个没有排序的提议,对所选项目使用帮助程序数组random

首先得到一个空的数组,然后用true填充,直到count元素被填充并且过滤掉具有随机选择位置的原始数组。

此解决方案适用于给定数组的任何内容,无需使用indexOf进行排序或查找。

function getSortedRandom(array, count) { 
 
    var random = array.map(function() { return false; }), 
 
     r; 
 

 
    while (count) { 
 
     r = Math.floor(Math.random() * array.length); 
 
     if (!random[r]) { 
 
      random[r] = true; 
 
      count--; 
 
     } 
 
    } 
 
    return array.filter(function (_, i) { 
 
     return random[i]; 
 
    }); 
 
} 
 

 
var random = getSortedRandom(["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18"], 5); 
 

 
document.write('<pre>' + JSON.stringify(random, 0, 4) + '</pre>');

0

由于lodash 4.0.0的,你可以结合使用_.sampleSize功能与sort:包含数字

var numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18"]; 
 

 
var randomSample = _.sampleSize(numbers, 5).sort(); 
 

 
console.log(randomSample);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>

相关问题