在JavaScript中改组数组属性

时间:2011-05-22 20:41:44

标签: javascript random swap shuffle

我有这样的数据字典:

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()排序,但是我仍然坚持交换这些值,因为没有密钥应该具有它最初的相同值。

你会如何在这里交换键/值?

由于

5 个答案:

答案 0 :(得分: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/

答案 1 :(得分:1)

你可以这样做:

  • 收集两个数组中的名称和相应值名称
  • 将两个阵列彼此独立地混洗
  • 获取两个阵列的第一个 n 项目并将它们合并

以下是一个示例实现:

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;
}

答案 2 :(得分:0)

使用随机化实现随机化一组离散值,例如Math.rand seen here。对于每个索引,随机化Math.rand(index, length-1)以获得随机索引列表,所有索引的位置都将发生变化。

答案 3 :(得分: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;
  }

答案 4 :(得分: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, 最诚挚的问候。