在 JavaScript 中打乱数组属性

发布于 2024-11-09 05:16:02 字数 492 浏览 0 评论 0原文

我有一个像这样的数据字典:

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() 排序,但我坚持交换值,因为没有键应该具有与最初具有相同的值。

您将如何在这里交换键/值?

谢谢

I have a data dictionary like this:

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

I need to pick a random selection of those keys and then shuffle it's values. In the example, it should write something like this:

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

For now I'm extracting the keys into another array and sorting by Math.random() but I'm stuck at swaping the values because no key should have the same value it initially had.

How would you swap key/values here?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦屿孤独相伴 2024-11-16 05:16:02

我使用 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/

I put together a possible solution using underscore.js to simplify traversing the object and arrays in a cross browser manner:

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

This isn't necessarily an optimal approach but it seems to meet your requirements. I first grab all of the keys and sort them randomly. I then loop through the random keys creating a new object with one key and the following keys value. That way you'll always end up with a different value associated with each key. If you need it to work when the value of num passed in to the function == the number of keys in the data then you'll have to add a little more code - I'll leave that as an exercise for the reader :)

You can have a play with this code on jsfiddle:

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

阳光下的泡沫是彩色的 2024-11-16 05:16:02

您可以这样做:

  • 在两个数组 namesvalues 中收集名称和相应的值,
  • 相互独立地对两个数组进行洗牌,
  • 获取前 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;
}

You could do this:

  • collect names and corresponding values in two arrays names and values
  • shuffle both arrays independently of each other
  • take the first n items of both arrays and combine them

Here’s an example implementation:

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;
}
阪姬 2024-11-16 05:16:02

自从回答这个问题以来已经有一段时间了,但我正在研究洗牌,发现以下是迄今为止最快的均匀随机分布的实现。

它之所以很快,是因为它在每次迭代中只调用一次 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;
  }

Been a while since this was answered, but I was working on shuffling and found the following to be by far the fastest implementation with an evenly random distribution.

It's fast because it only makes one call to Math.random on each iteration, all the rest is done by property access. It doesn't modify the array, just reassigns values.

  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;
  }
醉梦枕江山 2024-11-16 05:16:02

它使用三个函数的组合(包括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);
}  

检查所有帖子
此致。

It uses a combination of three functions (including the Array shuffle prototype method).

Here is the complete code:

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,
Best Regards.

烟酒忠诚 2024-11-16 05:16:02

使用 random 的实现来随机化一组离散值,例如 Math.rand 见此处。对于每个索引,随机化 Math.rand(index, length-1) 以获得随机索引列表,所有索引的位置都会改变。

Use an implementation of random that randomizes a discrete set of values, such as Math.rand seen here. For each index, randomize Math.rand(index, length-1) to get a list of random indexes, the location off all indices will change.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文