我想随机洗牌一个包含4个项目的列表,但是只要你有相同的种子,你就可以获得相同的项目顺序。
["a", "b", "c", "d"]
我想我可以用Math.random获取种子,我不需要非常精确的东西。我如何根据种子排序?
答案 0 :(得分:1)
的 jsFiddle Demo
强> 的
就我所知,您需要为数组中的每个值设置一个随机值。在这方面,你可能想要做这样的事情:
for( var i = 0; i < length; i++ ){
seed.push(Math.random());
}
您确保length
的长度与种子的长度相同。对于您的简单示例,这将是4。完成后,您可以将种子传递到您的shuffle(或sort)函数中,以确保获得相同的结果。 shuffle也需要在循环中使用它
var randomIndex = parseInt(seed[i] * (len - i));
所以这就是所有分解为
的内容将存储种子数组的种子函数
var seeder = function(){
var seed = [];
return {
set:function(length){
for( var i = 0; i < length; i++ ){
seed.push(Math.random());
}
return seed;
},
get: function(){
return seed;
},
clear: function(){
seed = [];
}
};
}
非常基本的随机播放
function randomShuffle(ar,seed){
var numbers = [];
for( var a = 0, max = ar.length; a < max; a++){
numbers.push(a);
}
var shuffled = [];
for( var i = 0, len = ar.length; i < len; i++ ){
var r = parseInt(seed[i] * (len - i));
shuffled.push(ar[numbers[r]]);
numbers.splice(r,1);
}
return shuffled;
}
正在使用
var arr = ["a", "b", "c", "d"];
var seed = seeder();
seed.set(arr.length);
console.log(randomShuffle(arr,seed.get()));
console.log(randomShuffle(arr,seed.get()));
console.log(randomShuffle(arr,seed.get()));
答案 1 :(得分:1)
适用于节点和浏览器。
答案 2 :(得分:1)
您可以对Fisher_Yates算法*的Mike Bostock's implementation进行一些修改来实现此目的:
function shuffle(array, seed) { // <-- ADDED ARGUMENT
var m = array.length, t, i;
// While there remain elements to shuffle…
while (m) {
// Pick a remaining element…
i = Math.floor(random(seed) * m--); // <-- MODIFIED LINE
// And swap it with the current element.
t = array[m];
array[m] = array[i];
array[i] = t;
++seed // <-- ADDED LINE
}
return array;
}
function random(seed) {
var x = Math.sin(seed++) * 10000;
return x - Math.floor(x);
}
* random
函数取自this SO answer。这是骇客行为,并非完全随机,最重要的是不是加密安全的! Here's a histogram of samples(也在该回复的注释中,需要一段时间才能运行)。结论是,只有在这些事情并不重要时,才应使用此功能。或者,用更好的种子随机数生成器代替random
函数。
答案 3 :(得分:1)
用种子打乱数组是两个不同的问题:
有关随机数生成器的种子,请参阅线程 fantastic answer 中的此 Seeding the random number generator in Javascript。
要对数组进行混洗,请参阅 Fisher-Yates 中的 How can I shuffle an array? 混洗。
这里有一些代码可以方便地将两者包装在一起。您可以从 this answer 复制和粘贴几个小函数。如果代码发生变化,我宁愿不去欺骗它,这让您可以即插即用您想要的任何种子随机函数。
// TODO: copy and paste mulberry32 and xmur3 from
// https://stackoverflow.com/a/47593316/6243352
const seededRandom = ({rng = null, seed = "apples"} = {}) => {
rng = rng || mulberry32(xmur3(seed)());
const rnd = (lo, hi, defaultHi=1) => {
if (hi === undefined) {
hi = lo === undefined ? defaultHi : lo;
lo = 0;
}
return rng() * (hi - lo) + lo;
};
const rndInt = (lo, hi) => Math.floor(rnd(lo, hi, 2));
const shuffle = a => {
for (let i = a.length - 1; i > 0; i--) {
const j = rndInt(i + 1);
const x = a[i];
a[i] = a[j];
a[j] = x;
}
};
return {rnd, rndInt, shuffle};
};
module.exports = seededRandom;
你可以像这样使用它:
const seededRandom = require("./seeded-random");
const {
rnd, rndInt, shuffle
} = seededRandom({seed: "optional seed string"});
const a = [...Array(5)].map((_, i) => i);
shuffle(a);
// comments assume mulberry32 and xmur3 from
// https://stackoverflow.com/a/47593316/6243352
console.log(a); // => always [ 2, 0, 3, 1, 4 ]
console.log(rnd()); // => always 0.8192486129701138
console.log(rndInt(42)); // => always 41
答案 4 :(得分:0)
您可以使用XOR Shift方法创建随机数来进行排序。
Example.
然后,使用Math.random()
new Xor128(seed).make(3)[2] / 4294967296 * 2