如何在JavaScript中对字符串中的字符进行随机播放?

时间:2010-10-15 15:37:45

标签: javascript string

特别是,我想确保避免在Microsoft的Browser Choice shuffle代码中犯下的错误。也就是说,我想确保每个字母在每个可能的位置都有相同的概率。

e.g。给定“ABCDEFG”,返回类似“GEFBDCA”的内容。

14 个答案:

答案 0 :(得分:70)

我修改了从Fisher-Yates Shuffle entry on Wikipedia到shuffle字符串的示例:

String.prototype.shuffle = function () {
    var a = this.split(""),
        n = a.length;

    for(var i = n - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
    return a.join("");
}
console.log("the quick brown fox jumps over the lazy dog".shuffle());
//-> "veolrm  hth  ke opynug tusbxq ocrad ofeizwj"

console.log("the quick brown fox jumps over the lazy dog".shuffle());
//-> "o dt hutpe u iqrxj  yaenbwoolhsvmkcger ozf "

可在Jon Skeet's answerIs it correct to use JavaScript Array.sort() method for shuffling?中找到更多信息。

答案 1 :(得分:37)

如果“真正”的随机性很重要,我建议不要这样做。请参阅下面的编辑。

我只想添加一些我最喜欢的方法;)

给出一个字符串:

var str = "My bologna has a first name, it's O S C A R.";

一行洗牌:

var shuffled = str.split('').sort(function(){return 0.5-Math.random()}).join('');

输出:

oa, a si'rSRn f gbomi. aylt AtCnhO ass eM
as'oh ngS li Ays.rC nRamsb Oo ait a ,eMtf
y alCOSf e gAointsorasmn bR Ms .' ta ih,a
编辑:正如@PleaseStand所指出的那样,这根本不符合OP的问题,因为它确实遭受了“微软的浏览器选择改组”代码。如果你的字符串需要接近随机,这不是一个非常好的随机函数。然而,令人敬畏的是快速“混乱”你的字符串,其中“真正的”随机性是无关紧要的。

下面链接的文章是一本很好的读物,但解释了一个完全不同的用例,它会影响统计数据。我个人无法想象在字符串上使用这个“随机”函数的实际问题,但作为编码器,你有责任知道何时使用它。

我把这里的所有休闲随机发生器留在了这里。

答案 2 :(得分:6)

尽管已经回答了这个问题,但我想分享一下我提出的解决方案:

function shuffelWord (word){
    var shuffledWord = '';
    word = word.split('');
    while (word.length > 0) {
      shuffledWord +=  word.splice(word.length * Math.random() << 0, 1);
    }
    return shuffledWord;
}

// 'Batman' => 'aBmnta'

您也可以try it out (jsfiddle)

答案 3 :(得分:6)

最短的一层:

const shuffle = v=>[...v].sort(_=>Math.random()-.5).join('');

不保证统计分布均等,但在大多数情况下对我有用。

const shuffle = v=>[...v].sort(_=>Math.random()-.5).join('');
document.write(shuffle("The quick brown fox jumps over the lazy dog"));

答案 4 :(得分:2)

使用Fisher-Yates随机播放算法和ES6:

// Original string
let string = 'ABCDEFG';

// Create a copy of the original string to be randomized ['A', 'B', ... , 'G']
let shuffle = [...string];

// Defining function returning random value from i to N
const getRandomValue = (i, N) => Math.floor(Math.random() * (N - i) + i);

// Shuffle a pair of two elements at random position j (Fisher-Yates)
shuffle.forEach( (elem, i, arr, j = getRandomValue(i, arr.length)) => [arr[i], arr[j]] = [arr[j], arr[i]] );

// Transforming array to string
shuffle = shuffle.join('');

console.log(shuffle);
// 'GBEADFC'

答案 5 :(得分:1)

仅出于完整性考虑,尽管这可能并不是OP所要求的,因为该特定问题已经得到了回答。

这是一个随机的单词。

这是正则表达式的解释:https://regex101.com/r/aFcEtk/1

它也有一些有趣的结果。

// Shuffles words
// var str = "1 2 3 4 5 6 7 8 9 10";
var str = "the quick brown fox jumps over the lazy dog A.S.A.P. That's right, this happened.";
var every_word_im_shuffling = str.split(/\s\b(?!\s)/).sort(function(){return 0.5-Math.random()}).join(' ');
console.log(every_word_im_shuffling);

答案 6 :(得分:1)

您不能原地打乱 string,但您可以使用它:

String.prototype.shuffle = function() {
    var len = this.length;
    var d = len;
    var s = this.split("");
    var array = [];
    var k, i;
    for (i = 0; i < d; i++) {
        k = Math.floor(Math.random() * len);
        array.push(s[k]);
        s.splice(k, 1);
        len = s.length;
    }
    for (i = 0; i < d; i++) {
        this[i] = array[i];
    }
    return array.join("");
}

var s = "ABCDE";
s = s.shuffle();
console.log(s);

答案 7 :(得分:1)

单行解决方案和有限的输出长度...

var rnd = "ABCDEF23456789".split('').sort(function(){return 0.5-Math.random()}).join('').substring(0,6);

答案 8 :(得分:0)

String.prototype.shuffle=function(){

   var that=this.split("");
   var len = that.length,t,i
   while(len){
    i=Math.random()*len-- |0;
    t=that[len],that[len]=that[i],that[i]=t;
   }
   return that.join("");
}

答案 9 :(得分:0)

                  shuffleString = function(strInput){
                     var inpArr = strInput.split("");//this will give array of input string
                     var arrRand = []; //this will give shuffled array
                     var arrTempInd = []; // to store shuffled indexes
                     var max = inpArr.length;
                     var min = 0;
                     var tempInd;
                     var i =0 ;

                      do{
                           tempInd = Math.floor(Math.random() * (max - min));//to generate random index between range
                           if(arrTempInd.indexOf(tempInd)<0){ //to check if index is already available in array to avoid repeatation
                                arrRand[i] = inpArr[tempInd]; // to push character at random index
                                arrTempInd.push(tempInd); //to push random indexes 
                                i++;
                            }
                       }
                        while(arrTempInd.length < max){ // to check if random array lenght is equal to input string lenght
                            return arrRand.join("").toString(); // this will return shuffled string
                        }
                 };

只需将字符串传递给函数,然后返回获取随机字符串

答案 10 :(得分:0)

对单词进行加扰的另一种方式。具有迭代次数的所有其他答案将返回未加密的单词,而我的则不会。

var scramble = word => {

    var unique = {};
    var newWord = "";
    var wordLength = word.length;

    word = word.toLowerCase(); //Because why would we want to make it easy for them?

    while(wordLength != newWord.length) {

        var random = ~~(Math.random() * wordLength);

        if(

          unique[random]
          ||
          random == newWord.length && random != (wordLength - 1) //Don't put the character at the same index it was, nore get stuck in a infinite loop.

        ) continue; //This is like return but for while loops to start over.

        unique[random] = true;
        newWord += word[random];

    };

    return newWord;

};

scramble("God"); //dgo, gdo, ogd

答案 11 :(得分:0)

如果您像我一样追求整洁美观的单线,您可能会喜欢我的ES6实现:

const str = 'ABCDEFG';

const shuffle = str => [...str].reduceRight((res,_,__,arr) => [...res,arr.splice(~~(Math.random()*arr.length),1)[0]],[]).join('');

console.log(shuffle(str));

答案 12 :(得分:0)

Rando.js使用Fisher-Yates shuffle的加密安全版本,并且简短易读。

console.log(randoSequence("This string will be shuffled.").join(""));
<script src="https://randojs.com/2.0.0.js"></script>

答案 13 :(得分:-1)

String.prototype.shuffle = function(){
  return this.split('').sort(function(a,b){
    return (7 - (Math.random()+'')[5]);
  }).join('');
};