vb.net visual-studio-2008 list random

¿Hay alguna manera fácil de aleatorizar una lista en VB.NET?



visual-studio-2008 random (8)

Tengo una lista de tipo System.IO.FileInfo , y me gustaría aleatorizar la lista. Pensé que recuerdo haber visto algo así como list.randomize() un rato, pero no puedo encontrar dónde pude haber visto eso.

Mi primera incursión en esto me produjo esta función:

Private Shared Sub GetRandom(ByVal oMax As Integer, ByRef currentVals As List(Of Integer)) Dim oRand As New Random(Now.Millisecond) Dim oTemp As Integer = -1 Do Until currentVals.Count = IMG_COUNT oTemp = oRand.Next(1, oMax) If Not currentVals.Contains(oTemp) Then currentVals.Add(oTemp) Loop End Sub

Le envío el valor máximo que quiero que itere, y una referencia a la lista en la que quiero el contenido aleatorizado. La variable IMG_COUNT se establece más arriba en la secuencia de comandos, designando cuántas imágenes aleatorias quiero mostrar.

Gracias chicos, lo aprecio: D



Hay varios métodos razonables de barajar.

Uno ya ha sido mencionado. (The Knuth Shuffle.)

Otro método sería asignar un "peso" a cada elemento y ordenar la lista de acuerdo con ese "peso". Este método es posible pero sería poco sofisticado porque no puede heredar de FileInfo.

Un método final sería seleccionar aleatoriamente un elemento en la lista original y agregarlo a una nueva lista. Por supuesto, eso es, si no te importa crear una nueva lista. (No he probado este código ...)

Dim rnd As New Random Dim lstOriginal As New List(Of FileInfo) Dim lstNew As New List(Of FileInfo) While lstOriginal.Count > 0 Dim idx As Integer = rnd.Next(0, lstOriginal.Count - 1) lstNew.Add(lstOriginal(idx)) lstOriginal.RemoveAt(idx) End While


Puede crear un comparador personalizado que simplemente devuelve un número aleatorio, luego ordenar la lista usando este comparador. Podría ser terriblemente ineficiente y causar un ciclo casi infinito, pero podría valer la pena intentarlo.


Si tiene la cantidad de elementos, se puede usar un método pseudoaleatorio mediante el cual se elige el primer elemento al azar (por ejemplo, usando la función de número aleatorio incorporado), luego se agrega un primo y se toma el resto después de la división por el número de valores. por ejemplo, para una lista de 10, podría hacer i = (i + prime)% 10 para los índices generados i a partir de algún valor inicial. Siempre que el primo sea mayor que el número de valores en la lista, entonces usted crea una secuencia que se ejecuta a través de todos los números 0 ... n donde n es el número de valores - 1, pero en un orden pseudoaleatorio.


También puede implementar un orden aleatorio, de muchas maneras para hacer esto, lo más simple es elegir aleatoriamente un elemento e insertarlo en una nueva ubicación un montón de veces.


Construye un Comparador:

Public Class Randomizer(Of T) Implements IComparer(Of T) ''''// Ensures different instances are sorted in different orders Private Shared Salter As New Random() ''''// only as random as your seed Private Salt As Integer Public Sub New() Salt = Salter.Next(Integer.MinValue, Integer.MaxValue) End Sub Private Shared sha As New SHA1CryptoServiceProvider() Private Function HashNSalt(ByVal x As Integer) As Integer Dim b() As Byte = sha.ComputeHash(BitConverter.GetBytes(x)) Dim r As Integer = 0 For i As Integer = 0 To b.Length - 1 Step 4 r = r Xor BitConverter.ToInt32(b, i) Next Return r Xor Salt End Function Public Function Compare(x As T, y As T) As Integer _ Implements IComparer(Of T).Compare Return HashNSalt(x.GetHashCode()).CompareTo(HashNSalt(y.GetHashCode())) End Function End Class

Úselo así, suponiendo que se refiera a una List(Of FileInfo) genérica List(Of FileInfo) :

list.Sort(New Randomizer(Of IO.FileInfo)())

También puede usar un cierre para hacer que el valor aleatorio sea ''adhesivo'' y luego simplemente use .ql''s .OrderBy () en eso (C # esta vez, porque la sintaxis lambda de VB es fea):

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

Explicado aquí, junto con por qué podría no ser tan rápido como el barajado real:
http://www.codinghorror.com/blog/archives/001008.html?r=31644


Dim oRand As New Random() ''do not seed!!!! Private Sub GetRandom(ByRef currentVals As List(Of Integer)) Dim i As New List(Of Integer), j As Integer For x As Integer = 0 To currentVals.Count - 1 j = oRand.Next(0, currentVals.Count) i.Add(currentVals(j)) currentVals.RemoveAt(j) Next currentVals = i End Sub


Amplié la clase List con la siguiente función Randomize() para utilizar el algoritmo de mezcla de Fisher-Yates:

'''''' <summary> '''''' Randomizes the contents of the list using Fisher–Yates shuffle (a.k.a. Knuth shuffle). '''''' </summary> '''''' <typeparam name="T"></typeparam> '''''' <param name="list"></param> '''''' <returns>Randomized result</returns> '''''' <remarks></remarks> <Extension()> Function Randomize(Of T)(ByVal list As List(Of T)) As List(Of T) Dim rand As New Random() Dim temp As T Dim indexRand As Integer Dim indexLast As Integer = list.Count - 1 For index As Integer = 0 To indexLast indexRand = rand.Next(index, indexLast) temp = list(indexRand) list(indexRand) = list(index) list(index) = temp Next index Return list End Function