2011-05-22 55 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, 问候。