【问题标题】:Most efficient array shuffler [duplicate]最有效的数组洗牌器[重复]
【发布时间】:2011-11-10 16:22:29
【问题描述】:

如何以最有效的方式对数组的值进行洗牌?

每个元素只是一个包含 HTML 的字符串。

【问题讨论】:

标签: javascript arrays shuffle performance


【解决方案1】:

让我发布我自己的答案只是为了鼓励您不要使用随机的sort() 方法,因为它会产生不是那么随机的输出。

正如所说,Fisher-Yates shuffle 是最适合该目的的efficient 算法,并且可以使用以下 ES6 代码轻松实现:

const src = [...'abcdefg'],

      shuffle = arr => arr.reduceRight((r,_,__,s) => 
        (r.push(s.splice(0|Math.random()*s.length,1)[0]), r),[])

console.log(JSON.stringify(shuffle(src)))
.as-console-wrapper {min-height:100%}

【讨论】:

    【解决方案2】:

    这是我洗牌数组的解决方案:

        function shuffle(array) {
           var resultArray = new Array();
           for(i=0;i<array.length;i++) {
               var randomEle = Math.floor(Math.random()*array.length);
               resultArray.push(array[randomEle]);
               array.splice(randomEle,1);
           }
           resultArray = resultArray.concat(array);
           return resultArray;
        }
    

    这是一个随机比赛,将我的方法与其他 2 个方法进行比较

    http://jsperf.com/shuffle-contest/2

    【讨论】:

    • 我已将来自@alex 的answer 的Fisher-Yates shuffle 添加到您的jsPerf 'contest'。这是最快的
    【解决方案3】:

    你有几个选择。

    首先,您可以使用愚蠢的排序器...

    arr = arr.sort(function() {
        return Math.random() - .5
    });
    

    jsFiddle.

    这是快速而肮脏的,但通常被认为是不好的做法。

    Further Reading.

    随机排序Array最佳方法是使用Fisher-Yates shuffle

    var newArr = [];
    
    while (arr.length) {
    
       var randomIndex = Math.floor(Math.random() * arr.length),
           element = arr.splice(randomIndex, 1)
    
       newArr.push(element[0]);       
    
    }
    

    JSBin.

    【讨论】:

    • 你怎么给我一个 "often considered bad practice" 的 jsfiddle 链接而不是 Fisher-Yates shuffle?
    • @Adam 现在只是写费舍尔耶茨,不得不查一下:)
    • 没关系。我将使用stackoverflow.com/questions/962802/…
    • OpenDNS:"Phishing Site Blocked Phishing is a fraudulent attempt to get you to provide personal information under false pretenses."
    【解决方案4】:

    这是我使用的。它为每个元素提供一个随机数,按这些随机数对数组进行排序(移动实际值),然后再次删除随机数。它似乎是均匀分布的,但我还没有在数学上证明它。

    arr = arr.map(function(v) {
        return [v, Math.random()];
    }).sort(function(a, b) {
        return a[1] - b[1];
    }).map(function(v) {
        return v[0];
    });
    

    http://jsfiddle.net/XQRFt/ - 测试结果(可能很慢)

    【讨论】:

    • 这依赖于 ECMAScript 5 Array 方法,排除了 IE
    • @Tim Down:是的,你是对的。事实上,这些功能在速度方面也往往效率低下。但我个人觉得它更具可读性。
    猜你喜欢
    • 2013-02-24
    • 2017-07-31
    • 2017-06-24
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    相关资源
    最近更新 更多