如何在 JavaScript 中打乱字符串中的字符?

IT技术 javascript string
2021-01-15 07:26:36

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

例如,给定“ABCDEFG”,返回类似“GEFBDCA”的内容。

6个回答

我修改了Wikipedia 上 Fisher-Yates 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 "

更多信息可参见乔恩斯基特的回答是正确使用JavaScript的Array.sort()方法洗牌?.

谢谢,这绝对比我发现的其他一些例子更统一。
2021-03-15 07:26:36
请注意这个答案,它解释了如何在 ES6 中使用[a[i], a[j]] = [a[j], a[i]].
2021-03-21 07:26:36

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

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

给定一个字符串:

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 的问题,因为它确实受到“Microsoft 的浏览器选择洗牌”代码的影响。如果您的字符串需要接近随机,这不是一个很好的随机化器。然而,快速“混杂”你的字符串非常棒,“真正的”随机性是无关紧要的。

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

我已经把这个留在这里给所有的随意随机化器。

-1:这与“Microsoft 的浏览器选择 shuffle 代码中所犯的错误”完全相同。robweir.com/blog/2010/02/microsoft-random-browser-ballot.html
2021-03-27 07:26:36
@PleaseStand 你是完全正确的。我一直都知道这是一个非常懒惰的 hack,实际上并不会产生非常随机的结果。我会更新我的答案,虽然我不会说这是“确切的错误”——那是针对调查结果的。
2021-04-13 07:26:36

最短的一个班轮:

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

是的,这太棒了,我肯定会在生产代码中使用:D
2021-03-24 07:26:36
这太棒了——永远不会在生产代码中使用它——但太棒了。
2021-03-31 07:26:36

即使已经回答了这个问题,我还是想分享我想出的解决方案:

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'

你也可以试试 (jsfiddle)

小提琴不存在。
2021-04-03 07:26:36

使用Fisher-Yates shuffle 算法和 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'