2009-01-06 10 views

Respuesta

12

¿Qué tal un tipo de Knuth-Fisher-Yates shuffle algorithm?

for (int i = cards.Length - 1; i > 0; i--) 
{ 
    int n = rand.Next(i + 1); 
    Swap(ref cards[i], ref cards[n]); 
} 

Código tomado de Coding Horror. Esta es también una lectura recomendada sobre cómo las personas a menudo hacen esto mal.

+0

Código de formato como código. Pero buen algoritmo – recursive

+0

@recursive Gracias, reformateo el código. – Gant

1

Mi solución favorita para mezclar cosas es utilizar un tipo N * log N y pasarle un predicado de clasificación que arroje un resultado aleatorio. Tiene la característica agradable de que se puede hacer con un mínimo de código nuevo usando bloques de construcción que la mayoría de los lenguajes tienen a mano incluso en las versiones más rayadas.

+0

Por por otro lado, una mezcla aleatoria es solo O (n) y solo tiene unas 5 líneas de código, como se muestra en otras respuestas. (Y se puede hacer solo una vez con genéricos muy fácilmente.) –

+0

5 líneas a 1 línea no es mucho (solo 4 líneas) o mucho (80%). También es más simple de recordar. – BCS

+0

Y la otra ventaja es que el género podría aprovechar algo para obtener un buen rendimiento en los swaps, por lo que para n pequeño podría ser más rápido. – BCS

2

Puede usar el algoritmo Fisher-Yates shuffle que se ejecuta en tiempo lineal.

+0

Produce resultados incorrectos - vea http://www.codinghorror.com/blog/archives/001015.html –

+0

@LFSR: lea el artículo otra vez? – Jimmy

+0

¿Qué hay de Knuth? :( – configurator

0

lo haría crea una nueva lista y llénala con elementos que se seleccionan al azar y se eliminan de la lista original.

6

Salida este fresco manera LINQ de hacerlo:

public class Employee 
{ 
    public int Id 
    { 
     get; 
     set; 
    } 
    public string Name 
    { 
     get; 
     set; 
    } 
} 

rellenar una lista:

List<Employee> list = new List<Employee>(); 

    list.Add(new Employee { Id = 1, Name = "Davolio Nancy" }); 
    list.Add(new Employee { Id = 2, Name = "Fuller Andrew" }); 
    list.Add(new Employee { Id = 3, Name = "Leverling Janet" }); 
    list.Add(new Employee { Id = 4, Name = "Peacock Margaret" }); 
    list.Add(new Employee { Id = 5, Name = "Buchanan Steven" }); 
    list.Add(new Employee { Id = 6, Name = "Suyama Michael" }); 
    list.Add(new Employee { Id = 7, Name = "King Robert" }); 
    list.Add(new Employee { Id = 8, Name = "Callahan Laura" }); 
    list.Add(new Employee { Id = 9, Name = "Dodsworth Anne" }); 

Luego ordenar:

list = list.OrderBy(emp => Guid.NewGuid()).ToList(); 

Credit

+0

No es exactamente rápido, pero increíble. – Will

+0

¿A quién le importa el rendimiento cuando puedes sacar tu gran stick LINQ y mostrarle a otros que eres mejor que ellos? :-P – BFree

+0

Solo recuerde que los GUID ** ** no se tratan como números aleatorios para criptografía. Trabajarán para este tipo de cosas, pero no son intercambiables. –

0

probar este co here de

Utiliza el IComparer.Compare

Será una buena práctica si lo hace la función usando generics

Cuestiones relacionadas