Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 1 de mayo de 2018
Barajando el array Hace unos días, el amigo Fernando J., me escribía a través del formulario de contacto del blog preguntándome si tenía a mano alguna solución para "desordenar" aleatoriamente elementos de un array en VB y, aunque no es el lenguaje ni el tipo de cuestión que solemos tocar por aquí, sí me pareció interesante darle una respuesta que pudiera ser de utilidad a alguien más.

Hay varios algoritmos para conseguirlo, pero el llamado Fisher-Yates shuffle es muy eficiente (O(N)), no necesita almacenamiento extra, es fácil de implementar y ofrece unos resultados más que razonables. Este algoritmo permite generar una permutación aleatoria de un conjunto finito de elementos o, en otras palabras, desordenar los elementos de un array.

El código Visual Basic .NET:
Sub Shuffle(Of T)(values As IList(Of T))
    Dim n = values.Count()
    Dim rnd = New Random()
    Dim i = n - 1
    While i > 0
        Dim j = rnd.Next(0, i)
        Dim temp = values(i)
        values(i) = values(j)
        values(j) = temp
        i -= 1
    End While
End Sub

' Usage:
Dim array = New Integer() {1, 2, 3, 4}
Shuffle(array)
' Content of array (example): { 2, 3, 4, 1 }
Sencillo, ¿eh? Lo único que hacemos es intercambiar el elemento N con uno elegido aleatoriamente entre los N-1 restantes, y repetir de nuevo para el elemento N-1, N-2, y así sucesivamente. De esta forma se asegura que todos los elementos habrán cambiado su posición durante el proceso; si no es esto lo que queremos y preferimos permitir que algunos elementos no cambien de lugar, simplemente habría que modificar el valor máximo del número aleatorio generado, de forma que existirá la posibilidad de que el elemento tratado quede finalmente en su misma ubicación: rnd.Next(0, i+1).

El equivalente al código anterior en C# sería el siguiente:
public static void Shuffle<T>(IList<T> values)
{
    var n = values.Count;
    var rnd = new Random();
    for (int i = n - 1; i > 0; i--)
    {
        var j = rnd.Next(0, i);
        var temp = values[i];
        values[i] = values[j];
        values[j] = temp;
    }
}

// Usage:
var array = new[] {"a", "b", "c", "d"};
Shuffle(array);
// content of array (example): { "b", "d", "a", "c" }
Espero que pueda ser de ayuda :)

Publicado en Variable not found.

1 comentario:

Unknown dijo...

Muchísimas gracias, me has salvado, ya está colapsado y no sabía que hacer para lograr lo que quería.