Cómo obtener un número aleatorio de un rango, excluyendo algunos valores

En C #, ¿cómo obtengo un número aleatorio de un rango de valores, como 1..100, pero ese número no debe estar en una lista específica de valores, como 5, 7, 17, 23?

Como nadie ha publicado ningún código de ejemplo:

private int GiveMeANumber() { var exclude = new HashSet() { 5, 7, 17, 23 }; var range = Enumerable.Range(1, 100).Where(i => !exclude.Contains(i)); var rand = new System.Random(); int index = rand.Next(0, 100 - exclude.Count); return range.ElementAt(index); } 

Aquí está el pensamiento:

  1. Crea un Hashset de números que quieras excluir
  2. Cree una colección de todos los números 0-100 que no están en su lista de números para excluir con un poco de LINQ.
  3. Crea un objeto aleatorio.
  4. Utilice el objeto Random para darle un número entre 0 y la cantidad de elementos en su rango de números (inclusive).
  5. Devuelve el número en ese índice.

Si te importa Big O , mira este algoritmo. Supone que la matriz de valores excluidos se ordena en orden ascendente y contiene valores dentro de 0 y n-1 rango (inclusive).

 public static int random_except_list(int n, int[] x) { Random r = new Random(); int result = r.Next(n - x.Length); for (int i = 0; i < x.Length; i++) { if (result < x[i]) return result; result++; } return result; } 

Si lo llamas con:

 random_except_list(8, new int[]{3,4,6}) 

devolverá uno de los siguientes valores: 0 , 1 , 2 , 5 , 7 .

Este es el método de extensión que uso:

 Random random = new Random(); public static int RandomNumber(int minN, int maxN, IEnumerable exNumbers) { int result = exNumbers.First(); while (exNumbers.ToList().Contains(result)) { result = random.Next(minN, maxN + 1); } return result; } 

puede usar una instrucción do-while para elegir otra Aleatoria si es igual a qué número desea excluir. este código es para excluir el número que eligió antes

  int newNumber; do { newNumber = Random.Range (0, 100); } while(number == newNumber); number = newNumber; 

Cree una matriz que contenga todos los números que desee (o el contenedor que use su idioma) menos el número que no desee y seleccione al azar de la matriz.

Utilice una función para generar números aleatorios entre 1 y 100, que escribir una statement if, por ejemplo, si el número aleatorio es igual a 5, 7, 17, 23, genere el número aleatorio otra vez, use el número aleatorio que se generó en primer lugar .

Coloque los números permitidos en una matriz, genere un entero aleatorio de 0 a la longitud de esta matriz menos uno. Utilice este número entero como índice para obtener el número aleatorio de la matriz de números permitidos.


Si la matriz original contiene objetos grandes en lugar de números, entonces hacer otra matriz copiando profundamente los objetos permitidos no será efectiva. En este caso, la matriz de objetos permitidos solo debe contener un puntero, una referencia o un índice para los objetos en la matriz original. En este caso, genera un entero aleatorio para seleccionar un elemento de esta matriz y utiliza este puntero / referencia / índice para obtener el objeto seleccionado de la matriz original .

Aquí hay un ejemplo de trabajo para el caso general (¡solo una posible solución!):

 using System; using System.Collections.Generic; public static class RandomElementSelector { public static IList CollectAllowedElements(IList allElements, IList excludedElements) { List allowedElements = new List(); foreach (T element in allElements) if (!excludedElements.Contains(element)) allowedElements.Add(element); return allowedElements; } public static T SelectRandomElement(IList allowedElements) { Random random = new Random(); int randomIndex = random.Next(allowedElements.Count); return allowedElements[randomIndex]; } public static T SelectRandomElement(IList allElements, IList excludedElements) { IList allowedElements = CollectAllowedElements(allElements, excludedElements); return SelectRandomElement(allowedElements); } } public class Test { public static void Main() { const int N = 100; // Example #1 int[] allNumbers = new int[N]; for (int i = 0; i < allNumbers.Length; ++i) allNumbers[i] = i + 1; int[] excludedNumbers = { 5, 7, 17, 23 }; Console.WriteLine(RandomElementSelector.SelectRandomElement(allNumbers, excludedNumbers)); // Example #2 List allStrings = new List(); for (int i = 0; i < N; ++i) allStrings.Add("Item #" + (i + 1)); string[] excludedStrings = { "Item #5", "Item #7", "Item #17", "Item #23" }; Console.WriteLine(RandomElementSelector.SelectRandomElement(allStrings, excludedStrings)); } } 

Esto es lo que hago en esta situación, no es perfecto, pero funciona bien para mí. Normalmente lo hago solo por 1 número, pero así es como puede ser para un grupo de números excluidos:

Digamos que quiero excluir [5, 7, 17, 23] de un azar entre 1-100. Siempre tengo una sustitución para cada uno de los números excluidos, como [6, 8, 18, 24]. Si el número aleatorio cae en cualquiera de los números excluidos, lo reemplazo por su sustitución.

Vine aquí buscando una solución mejor, pero no pude encontrar ninguna, así que terminé compartiendo la mía.