2010-01-05 5 views
1

J'ai une chaîne séparée par des virgules, dont j'ai besoin de créer une nouvelle chaîne qui contient un ordre aléatoire des éléments de la chaîne d'origine, tout en s'assurant qu'il n'y a pas de récurrence. Par exemple: En cours d'exécution 1,2,3,1,3 donnera 2,3,1 et un autre temps 3,1,2, et ainsi de suite.Comment construire efficacement une liste aléatoire à partir d'une liste donnée sans récurrences dans JS?

J'ai un code qui sélectionne un élément aléatoire dans la chaîne d'origine, puis itère sur la nouvelle chaîne pour voir si elle n'existe pas déjà. Si ce n'est pas le cas, l'élément est inséré. Cependant, j'ai le sentiment que cela peut être amélioré (en C#, j'aurais utilisé une hashtable, au lieu d'itérer à chaque fois sur le nouveau tableau). Une amélioration peut être de supprimer l'élément que nous avons inséré du tableau original, afin d'éviter les cas où le nombre aléatoire nous donnera le même résultat, par exemple.

Je serais heureux si vous pouviez suggérer des améliorations au code ci-dessous.

originalArray = originalList.split(',');    
for (var j = 0; j < originalArray.length; j++) { 
    var iPlaceInOriginalArray = Math.round(Math.random() * (originalArray.length - 1)); 
    var bAlreadyExists = false;    
    for (var i = 0; i < newArray.length; i++) { 
     if (newArray[i].toString() == originalArray[iPlaceInOriginalArray].toString()) { 
      bAlreadyExists = true; 
      break; 
     } 
    } 

if (!bAlreadyExists) 
    newArray.push(originalArray[iPlaceInOriginalArray]); 
} 

Merci!

Répondre

1

Vous pouvez toujours utiliser un 'hachage' en javascript pour supprimer les doublons. Seulement en JS ils sont appelés objets:

function removeDuplicates(arr) { 
    var hash = {}; 
    for (var i=0,l=arr.length;i<l;i++) { 
     hash[arr[i]] = 1; 
    } 
    // now extract hash keys... ahem... 
    // I mean object members: 
    arr = []; 
    for (var n in hash) { 
     arr.push(n); 
    } 
    return arr; 
} 

Oh, et la sélection au hasard d'une chose de tableau. S'il est autorisé à détruire le tableau original (qui, dans votre cas, il est) puis utilisez épissure:

function randInt (n) {return Math.floor(Math.random()*n)} 

function shuffle (arr) { 
    var out = []; 
    while (arr.length) { 
     out.push(
      arr.splice(
       randInt(arr.length),1)); 
    } 
    return out; 
} 

// So: 
newArray = shuffle(
       removeDuplicates(
        string.split(','))); 
0

Avec votre solution, vous n'êtes pas certain de ne pas choisir le même numéro plusieurs fois, laissant ainsi d'autres ne jamais être choisis. Si le nombre d'éléments n'est pas important (jusqu'à 100), la suppression d'éléments du tableau source donnera le meilleur résultat.
Modifier

originalArray = originalList.split(',');    
for (var j = 0; j < originalArray.length; j++) { 
    var iPlaceInOriginalArray = Math.round(Math.random() * (originalArray.length - 1 - j)); 
var bAlreadyExists = false;    
for (var i = 0; i < newArray.length; i++) { 
    if (newArray[i].toString() == originalArray[iPlaceInOriginalArray].toString()) { 
     bAlreadyExists = true; 
     break; 
    } 
} 

var tmp = originalArray[originalArray.length - 1 - j]; 
originalArray[originalArray.Length - 1 - j] = originalArray[iPlaceInOriginalArray]; 
originalArray[iPlaceInOriginalArray] = tmp; 

if (!bAlreadyExists) 
    newArray.push(originalArray[iPlaceInOriginalArray]); 
} 
+0

Merci beaucoup, je n'ai pas remarqué. – Nir

1

// Si vous triez le premier tableau, il est plus rapide de sauter les doublons, et vous pouvez raccorder chaque élément unique, dans sa position aléatoire lorsque vous construisez le nouveau tableau.

var s = 'Fonction, String, Object, String, Array, Date, erreur, String, String,' + 'Math, Nombre, RegExp, Groupe, Collection, TimeLog, couleur, String';

var A1= s.split(',').sort(), A2= [], tem; 
while(A1.length){ 
tem= A1.shift(); 
while(A1[0]== tem) tem= A1.shift(); 
if(tem) A2.splice(Math.floor(Math.random()*A2.length), 0, tem); 
} 

alerte (A2.join (''))

+0

Merci, @kennebec! – Nir

Questions connexes