2011-08-20 19 views
7

Quindi, sto tentando di selezionare una voce casuale da una matrice, e quindi fare in modo che la voce particolare non sarà selezionata di nuovo fino a quando ogni voce è stata selezionata. Fondamentalmente, non voglio vedere nessuna delle stesse voci, fino a quando non sono state selezionate tutte le voci nell'array.Selezione di array casuali senza selezionare due volte in JavaScript

Quindi, se questo fosse il mio allineamento ...

keywords = 
[ 
"ppc", 
"games", 
"advertise", 
"meta", 
"home", 
"gaming", 
"welcome" 
] 
var keyword = keywords[Math.floor(Math.random()*keywords.length)] 
document.write(keyword); 

Non vorrei vedere una potenza di:

meta, advertise, home, meta, gaming, welcome, ppc, welcome 

dal meta è stata selezionata una seconda volta prima che tutto era stato selezionato una volta. Mi piacerebbe vedere qualcosa di più simile:.

meta, advertise, gaming,ppc, welcome, home, games, advertise, ppc, 

dal momento che questo Non hai scelto una voce più volte prima di ogni ingresso era stato scelto a caso (il secondo ciclo iniziato al secondo "pubblicizzare" nel caso in cui si didn' t prendere le differenze

Ma come potete vedere dal codice che ho postato sopra, non so come farlo.Ho visto esempi in cui le voci che sono state selezionate casualmente, sono state effettivamente cancellate dall'array interamente ma questo non è quello che voglio fare. Voglio solo che ogni voce sia selezionata una volta, e quindi per il processo da riavviare.

Qualcuno conosce il codice per questo?

+0

possibile duplicato di [serie di numeri casuali] (http://stackoverflow.com/questions/4373306/array-of-random-numbers) –

risposta

0

Se non vi dispiace modificare l'array, è possibile rendere casuale l'ordine degli elementi nell'array e quindi stampare l'array dal primo elemento all'ultimo.

O

Si potrebbe fare altro array di valori da 1 a N (dove n è il numero di elementi). Randomizza l'ordine di quell'array e poi lo usa come indice per l'array mentre lo iterai sopra dal primo all'ultimo.

0

Memorizza i numeri (indici) che hai visto in un hash, quindi quando provi a guardare una nuova parola puoi controllare l'hash, se l'hai già visto, generare un nuovo numero. Assicurati di controllare se la lunghezza dell'hash è uguale alla lunghezza dell'array.

Ciò evita di alterare la matrice.

+0

Ma supponiamo di avere una serie di indici di 1000, la probabilità di trovare un indice unico crescerebbe in modo esponenziale con ogni iterazione. Per l'ultima selezione avresti un 1 su 1000 di possibilità di terminare la funzione. Quindi il ciclo ripeterebbe un migliaio di volte in più, forse anche di più. Questo diventa anche più un problema quando si aggiungono indici. La tua funzione di prelievo potrebbe richiedere alcuni minuti. – Krythic

+0

La soluzione migliore è scegliere un indice casuale, quindi scambiare quell'indice alla fine dell'array con quello selezionato, quindi ripetere il ciclo usando (array.Length - 1 - i) Si garantisce una selezione ottimale di O/n. – Krythic

5

Un modo molto semplicistico per farlo sarebbe quello di utilizzare splice ogni volta che si seleziona un elemento casuale e una volta che l'array è vuoto ri-riempirlo con i valori originali.

Esempio:

(function() { 
    var arr = []; 

    window.getRandomThing = function() { 
     if (arr.length === 0) { 
      refill(); 
     } 

     return arr.splice(Math.random() * arr.length, 1)[0]; 
    }; 

    function refill() { 
     arr = [1,2,3,4,5]; 
    } 
}()); 
2

È possibile effettuare una copia della matrice originale, quindi utilizzare .splice() per afferrare un valore ad un indice caso, e rimuoverlo dal Array copia.

Poiché la copia viene ridotta di uno ogni volta, è sufficiente farlo while(copy.length).

Esempio:http://jsfiddle.net/fMXTF/

var keywords = [ 
"ppc", 
"games", 
"advertise", 
"meta", 
"home", 
"gaming", 
"welcome" 
]; 

var copy = keywords.slice(); 

while(copy.length) { 

    var keyword = copy.splice(Math.floor(Math.random()*copy.length), 1); 
    document.write(keyword + '<br>'); 

} 

noti che il numero casuale è basato copy.length, che, a causa della .splice(), viene diminuito di 1 a ogni iterazione. Pertanto assicura che il numero casuale si basi sempre sullo correntelength della copia.

+0

Questo ha funzionato alla grande per me! Grazie. – Abdel

7

È possibile utilizzare la funzione Array.sort() per ordinarla in modo casuale.

// random sort function 
function shuffle(a, b) 
{ 
    return Math.random() > 0.5 ? -1 : 1; 
} 

var keywords = ["ppc", "games", "advertise", "meta", "home", "gaming", "welcome"]; 

var randomKeywords = keywords.sort(shuffle); // new instance of a sorted randomly copy of the array 

alert(randomKeywords); 

aggiornamento:

Una soluzione migliore per rimescolamento utilizza Fisher-Yates Shuffle, come si trova in questo answer.

function shuffle(array) 
 
{ 
 
    var m = array.length, t, i; 
 
    while (m > 0) 
 
    { 
 
\t i = Math.floor(Math.random() * m--); 
 
\t t = array[m]; 
 
\t array[m] = array[i]; 
 
\t array[i] = t; 
 
    } 
 
    return array; 
 
} 
 

 
var keywords = ["ppc", "games", "advertise", "meta", "home", "gaming", "welcome"]; 
 

 
shuffle(keywords); // shuffles the array 
 

 
alert(keywords);

+0

Questo non funziona per me con Firefox e Opera su Linux. Ho bisogno di togliere il '-1' in' shuffle() '. Se l'ordinamento gestisce '0' dalla funzione di ordinamento dipende dall'implementazione, allora che ne dite' return (Math.random()> 0.5)? -1: 1; 'nel corpo di' shuffle() '? – sparklewhiskers

+0

Grazie, ho aggiornato la funzione shuffle. –

0

Stolen da user113716, ma ottimizzato un po '.

var arr = [ 
    "ppc", 
    "games", 
    "advertise", 
    "meta", 
    "home", 
    "gaming", 
    "welcome"]; 

Array.prototype.shuffle = Array.prototype.shuffle || function() { 
    var copy = this.slice(), arr = []; 
    while (copy.length) arr.push(copy.splice((Math.random() * copy.length) << 0)); 
    return arr; 
}; 

alert(arr.shuffle()); 
Problemi correlati