2011-05-22 116 views
1

我有這樣一個數據字典:洗牌陣列屬性在JavaScript

var data = { 
    'text1': 1, 
    'text2': 2, 
    'text3': 3, 
    ... 
    'text20': 20 
]; 

我需要選擇那些鍵的隨機選擇,然後打亂它的價值。在這個例子中,它應該寫這樣的事情:

> console.log(choose(data, 5)); 
[ { key: 'text15', value: 8 }, 
{ key: 'text6', value: 3 }, 
{ key: 'text3', value: 15 }, 
{ key: 'text19', value: 6 }, 
{ key: 'text8', value: 19 } ] 

現在我提取鍵到另一個陣列和的Math.random(排序),但我被困在swaping的值,因爲沒有鑰匙應具有最初的相同價值。

你會如何在這裏交換關鍵值?

由於

+0

是否有或沒有更換?例如'text8'的值可以出現兩次嗎? – ninjagecko 2011-05-22 20:46:46

+0

不,不能有重複的值。 – 2011-05-22 20:48:33

+0

你是什麼意思「沒有鑰匙應該有它最初的相同價值」?同樣用一個關鍵函數'Math.random()'排序並不會給你一個等概率的排列;它取決於所使用的排序算法。你必須通過'Math.random()'獲得N個鍵,存儲這些鍵,然後按它們排序。 – ninjagecko 2011-05-22 20:57:06

回答

1

我放在一起使用underscore.js簡化遍歷對象和陣列中一個跨瀏覽器方式的可能解決方案:

var data = { 
    text1: 1, 
    text2: 2, 
    text3: 3, 
    text4: 4, 
    text5: 5, 
    text6: 6, 
    text7: 7, 
    text8: 8, 
    text9: 9, 
    text10: 10 
}; 

function choose(data, num) 
{ 
    var keys = _.sortBy(
        _.keys(data), 
        function(k) 
        { 
         return (Math.random() * 3) - 1; 
        } 
       ), 
     results = [], 
     k1, k2; 
    if (num > keys.length) { 
     throw new Error('Impossible to retrieve more values than exist'); 
    } 
    while (results.length < num) { 
     k1 = k2 || keys.pop(); 
     k2 = keys.pop(); 
     results.push({key:k1, value: data[k2]}); 
    } 
    return results; 
} 

console.log(choose(data, 5)); 

這不一定是最佳的方法,但它似乎滿足你的要求。我首先抓住所有的鑰匙並隨機排序。然後我通過隨機鍵循環創建一個具有一個鍵和下面的鍵值的新對象。這樣你總是會得到與每個鍵相關的不同值。如果你需要它的工作,當num的值傳遞給函數==數據中的鍵的數量,那麼你將不得不添加更多的代碼 - 我將留給讀者作爲練習:)

您可以使用此代碼播放上的jsfiddle:

http://jsfiddle.net/zVyQW/1/

+0

非常類似於我的解決方案,但是||訣竅比增加兩個計數器更好。我給你的觀點。 – 2011-05-22 22:53:21

+0

如果您想要n個項目,您需要n + 1個鍵才能獲得第n個值,則這會失敗。 – Gumbo 2011-05-23 07:28:33

+0

@Gumbo - 正如你所看到的,如果你閱讀我在代碼下寫的東西,那麼這對閱讀者來說是一個(相當不重要的)練習... – vitch 2011-05-23 10:15:54

0

使用隨機的實現,隨機化一組離散的值,如Math.rand seen here。對於每個指數,隨機指定Math.rand(index, length-1)以獲得隨機指標列表,所有指數的位置都將改變。

1

你可以這樣做:

  • 收集的名稱和相應的值在兩個數組
  • 洗牌兩個數組相互獨立的
  • 採取先ñ項目並將它們組合在一起

下面是一個示例實現:

Array.prototype.shuffle = function() { 
    for (var i=this.length-1, j, tmp; i>0; i--) { 
     j = Math.round(Math.random()*i); 
     tmp = this[i], this[i] = this[j], this[j] = tmp; 
    } 
    return this; 
}; 

function choose(data, number) { 
    var names = [], values = [], pick = []; 
    for (var name in data) { 
     if (data.hasOwnProperty(name)) { 
      names.push(name); 
      values.push(data[name]); 
     } 
    } 
    names = names.shuffle(), values = values.shuffle(); 
    for (var i=Math.min(number >>> 0, names.length-1); i>=0; i--) { 
     pick.push({key: names[i], value: values[i]}); 
    } 
    return pick; 
} 
0

了,因爲這一段時間有人接聽,但我工作的洗牌,發現下面是目前爲止最快的實現與均勻隨機分佈。

這很快,因爲在每次迭代中它只會調用一次Math.random,其餘的都是通過屬性訪問完成的。它不修改數組,只是重新賦值。

function shuffle(a) { 
    var t, j, i=a.length, rand=Math.random; 

    // For each element in the array, swap it with a random 
    // element (which might be itself) 
    while (i--) { 
     k = rand()*(i+1)|0; 
     t = a[k]; 
     a[k]=a[i]; 
     a[i]=t; 
    } 
    return a; 
    } 
0

它使用三個函數的組合(包括Array shuffle原型方法)。

下面是完整的代碼:

var obj = { 
    "red":"RED", 
    "blue":"BLUE", 
    "green":"GREEN", 
    "yellow":"YELLOW", 
    "purple":"PURPLE" 
}; 

Array.prototype.shuffle = function(){ 
    for (var i = 0; i < this.length; i++){ 
     var a = this[i]; 
     var b = Math.floor(Math.random() * this.length); 
     this[i] = this[b]; 
     this[b] = a; 
    } 
} 

obj = shuffleProperties(obj); // run shuffle 

function shuffleProperties(obj) { 
    var new_obj = {}; 
    var keys = getKeys(obj); 
    keys.shuffle(); 
    for (var key in keys){ 
     if (key == "shuffle") continue; // skip our prototype method 
     new_obj[keys[key]] = obj[keys[key]]; 
    } 
    return new_obj; 
} 

function getKeys(obj){ 
    var arr = new Array(); 
    for (var key in obj) 
     arr.push(key); 
    return arr; 
} 


for(key in obj){ 
    alert(key); 
} 

Check all post, 問候。