58 votes

Comment mélanger les caractères d'une chaîne en JavaScript ?

En particulier, je veux m'assurer d'éviter l'erreur commise en Le choix du navigateur de Microsoft code shuffle. En d'autres termes, je veux m'assurer que chaque lettre a une probabilité égale de se retrouver dans chaque position possible.

Par exemple, étant donné "ABCDEFG", renvoyer quelque chose comme "GEFBDCA".

97voto

Andy E Points 132925

J'ai modifié un exemple tiré du Entrée Fisher-Yates Shuffle sur Wikipédia pour mélanger les cordes :

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 "

Vous trouverez de plus amples informations dans Réponse de Jon Skeet a Est-il correct d'utiliser la méthode JavaScript Array.sort() pour le brassage ? .

59voto

sudopeople Points 903

Si le caractère "vraiment" aléatoire est important, je vous le déconseille. Voir ma modification ci-dessous.

Je voulais juste ajouter ma méthode préférée pour varier un peu ;)

Étant donné une chaîne de caractères :

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

Mélangez en une seule ligne :

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

Sorties :

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

EDIT : Comme @PleaseStand l'a souligné, cela ne répond pas du tout à la question de l'OP puisqu'il souffre du code "Microsoft's Browser Choice shuffle". Ce n'est pas un très bon randomiseur si votre chaîne doit être proche du hasard. Il est cependant génial pour "brouiller" rapidement vos chaînes de caractères, là où le "vrai" caractère aléatoire n'est pas pertinent.

L'article dont il donne le lien ci-dessous est très intéressant à lire, mais il explique un cas d'utilisation complètement différent, qui concerne les données statistiques. Personnellement, je ne vois pas de problème pratique à l'utilisation de cette fonction "aléatoire" sur une chaîne de caractères, mais en tant que codeur, il vous incombe de savoir quand no pour l'utiliser.

Je l'ai laissé ici pour tous les randomiseurs occasionnels.

11voto

rturkek Points 77

La phrase la plus courte :

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

Ne garantit pas une distribution statistiquement égale mais est utilisable dans la plupart des cas pour moi.

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

0 votes

C'est génial - je ne l'utiliserais jamais dans un code de production - mais c'est génial.

3 votes

Oui, c'est génial, et je vais certainement l'utiliser dans un code de production :D

8voto

Bien que cette question ait déjà été traitée, je voulais partager la solution que j'ai trouvée :

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

// 'Batman' => 'aBmnta'

Vous pouvez également essayez-le (jsfiddle) .

Le snippet est un mélange de 100k chaînes de 3 caractères :

var arr={}, cnt=0, loops=100000, ret;
do{
  ret=shuffle('abc');
  arr[ret]=(ret in arr?arr[ret]+1:1);
}while(++cnt<loops);  

for(ret in arr){
  document.body.innerHTML+=ret+' '+arr[ret]+' '+(100*arr[ret]/loops).toFixed(1)+'%<br>';
}

function shuffle(wd){var t="";for(wd=wd.split("");wd.length>0;)t+=wd.splice(wd.length*Math.random()<<0,1);return t}

0 votes

J'ai testé le caractère aléatoire ; ça marche bien. Voici une version compressée : function shuffle(wd){var t="";for(wd=wd.split("");wd.length>0;)t+=wd.splice(wd.length‌​*Math.random()<<0,1)‌​;return t}

2voto

Utilisation de Fisher-Yates algorithme shuffle et 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'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X