2016-04-24 148 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>

相關問題