visual una repetir para numeros matriz llenar generar decimales con arreglo algoritmo aleatorios c# algorithm random code-review predicate

c# - para - llenar una matriz con numeros aleatorios sin repetir en c



Generar nĂºmeros aleatorios distintos en C# (9)

¡Cambié mi respuesta descuidada!

var result = new HashSet<int>(); var random = new Random(); var seq = Enumerable.Range(1, 30).GetEnumerator(); while(seq.MoveNext()) { while(!result.Add(random.Next(1, 100000))); }

Solo me preguntaba si podría confirmar que el siguiente código es válido y avisar si hay mejores alternativas para él.

Estoy intentando generar una colección de números aleatorios distintos entre 1 y 100000.

Random rand = new Random(); List<Int32> result = new List<Int32>(); for (Int32 i = 0; i < 300; i++) { Int32 curValue = rand.Next(1, 100000); while (result.Exists(value => value == curValue)) { curValue = rand.Next(1, 100000); } result.Add(curValue); }


En esos casos, siempre pienso que realmente no necesitas números aleatorios . En cambio, vas a barajar algunos números existentes.

Entonces, ¿qué tal si tomas el rango que te gusta con algo como var range = Enumerable.Range(1, 100000) , los barajas y tomas el número de elementos que necesitas, por algo como range.ToArray().Shuffle().Take(300) ?

Una implementación de un algoritmo de mezcla se puede encontrar aquí . Sé que no es un método de extensión, que puede usarse del modo descrito anteriormente, pero cambiar la firma es bastante fácil.


Esto hará lo que quieras, excepto que tirar un número porque lo has visto antes reduce la entropía (aleatoriedad) de la secuencia.


No es que importe mucho si solo ocasionalmente necesita 300 números, pero sería más eficiente usar HashSet que hace o (1) búsquedas en lugar de o (n) como con la Lista

Random rand = new Random(); HashSet<int> result = new HashSet<int>(); while (result.Count < 300) { result.Add(rand.Next(1, 1000000)); }


Sí, por lo que yo sé, el código hace exactamente lo que quieres.

Pasar por la lista para verificar cada valor no es muy eficiente. Puede poner los valores en un HashSet<int> para acelerar el ckeck.

Como el''HashSet'' no conserva el orden de los elementos, aún necesita la List :

Random rand = new Random(); List<int> result = new List<int>(); HashSet<int> check = new HashSet<int>(); for (Int32 i = 0; i < 300; i++) { int curValue = rand.Next(1, 100000); while (check.Contains(curValue)) { curValue = rand.Next(1, 100000); } result.Add(curValue); check.Add(curValue); }


Si estás dispuesto a tomar un golpe inicial para pregenerar una lista de 100,000 ints, este método es muy rápido:

static IList<int> GetRandoms(int[] sample) { var rand = new Random(); var result = new int[300]; var count = sample.Length; for (int i = 0; i < 300; i++) { var index = rand.Next(count); result[i] = sample[index]; sample[index] = sample[--count]; } return result; }

Entonces lo llamarías así:

var sample = Enumerable.Range(1, 100000).ToArray(); var data = GetRandoms(sample);


Tu versión funcionará, entonces lo que sugiero es solo una alternativa divertida:

List<Int32> result = new List<Int32>(); Queue<int> working = new Queue<int>(new int[2] {1, 100000}); Random rand = new Random(); while (result.Count < 300) { int lower = working.Dequeue(); int upper = working.Dequeue(); int pivot = rand.Next(lower,upper); result.Add(pivot); if(lower < pivot) { working.Enqueue(lower); working.Enqueue(pivot); } if(pivot+1 < upper) { working.Enqueue(pivot + 1); working.Enqueue(upper); } }


Reutilizar hombre Una vez que lo que quiere hacer es una colección de números (Enumerable.Range lo hará), lo segundo es mezclar (aleatoriamente) esos números. Puede encontrar la respuesta a este problema en SO, y gracias a la solución LINQ es hermosa, pero tal vez no la más rápida, de todos modos la uso, porque me gusta su belleza.

Mezcla de Linq: http://www.code56.com/2009/02/lets-do-some-shuffling.html (enlace inactivo). Implementación muy similar: http://csharpsimple.blogspot.com/2012/01/shuffle-in-linq-part-2.html

En breve:

var rand = new Random(); return source.Select(t => new { Index = rand.Next(), Value = t }) .OrderBy(p => p.Index) .Select(p => p.Value);


Me doy cuenta de que esta es una publicación realmente antigua, pero agregué mi experiencia reciente de hacer algo en la misma línea (tuve que generar 100k identificaciones de documentos aleatorios con identificaciones extranjeras en las que ambas tenían que ser listas únicas de #).

Para acelerarlo, es posible que desee multiprocesarlo con un parallel.for - si es así, no puede usar un hashset. En su lugar, utilice un byte byte en el que aparezca ConcurrentDictionary de <int, byte> donde el byte será un ''byte nuevo ()''

tomó el tiempo de ejecución de ~ 1.5 horas a aproximadamente 20 minutos para mí. Si debe hacerlo, le sugiero que también use una lista vinculada para almacenar, en lugar de una cola o lista, a menos que tenga una necesidad específica de acceso aleatorio.