![](/img/trans.png)
[英]Get a random array element index by excluding some of that array's element values
[英]How to get a random number from a range, excluding some values
在 C# 中,如何從一系列值中獲取隨機數 - 例如 1..100,但該數字不應出現在某些特定的值列表中,例如 5、7、17、23?
由於沒有人發布任何示例代碼:
private int GiveMeANumber()
{
var exclude = new HashSet<int>() { 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);
}
思路如下:
如果您關心Big O ,請查看此算法。 它假定排除的值數組按升序排序並包含0
和n-1
范圍(含)內的值。
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;
}
如果你用以下方式調用它:
random_except_list(8, new int[]{3,4,6})
它將返回以下值之一: 0
、 1
、 2
、 5
、 7
。
這就是我在這種情況下所做的,它並不完美,但對我來說效果很好。 我通常只為 1 個號碼執行此操作,但這就是一組排除號碼的處理方式:
假設我想從 1-100 之間的隨機數中排除 [5, 7, 17, 23]。 我總是替換每個排除的數字,例如 [6, 8, 18, 24]。 如果隨機數落入任何排除的數字中,我用它的替代品替換它。
我來到這里尋找更好的解決方案,但找不到任何解決方案,因此我最終分享了我的解決方案。
如果它等於要排除的數字,則可以使用 do-while 語句選擇另一個 Random 。 此代碼用於排除您之前選擇的數字
int newNumber;
do {
newNumber = Random.Range (0, 100);
} while(number == newNumber);
number = newNumber;
這是我使用的擴展方法:
Random random = new Random();
public static int RandomNumber(int minN, int maxN, IEnumerable<int> exNumbers)
{
int result = exNumbers.First();
while (exNumbers.ToList().Contains(result))
{
result = random.Next(minN, maxN + 1);
}
return result;
}
將允許的數字放入一個數組中,生成一個從 0 到該數組長度減 1 的隨機整數。 使用此整數作為索引從允許的數字數組中獲取隨機數本身。
如果原始數組包含大對象而不是數字,則通過深度復制允許的對象來創建另一個數組將無效。 在這種情況下,允許的對象數組應該只包含指向原始數組中對象的指針、引用或索引。 在這種情況下,您生成一個隨機整數來選擇此數組的一個元素,並使用此指針/引用/索引從原始數組中獲取所選對象本身。
這是一般情況下的工作示例(只是一種可能的解決方案!):
using System;
using System.Collections.Generic;
public static class RandomElementSelector
{
public static IList<T> CollectAllowedElements<T>(IList<T> allElements, IList<T> excludedElements)
{
List<T> allowedElements = new List<T>();
foreach (T element in allElements)
if (!excludedElements.Contains(element))
allowedElements.Add(element);
return allowedElements;
}
public static T SelectRandomElement<T>(IList<T> allowedElements)
{
Random random = new Random();
int randomIndex = random.Next(allowedElements.Count);
return allowedElements[randomIndex];
}
public static T SelectRandomElement<T>(IList<T> allElements, IList<T> excludedElements)
{
IList<T> 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<string> allStrings = new List<string>();
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));
}
}
創建一個包含您想要的所有數字(或您的語言使用的任何容器)減去所有您不想要的數字的數組,然后從數組中隨機選擇。
使用函數生成 1 到 100 之間的隨機數,然后編寫 if 語句,例如,如果隨機數等於 5、7、17、23,則再次生成隨機數,否則使用最初生成的隨機數.
來自 Java,但我很確定您可以輕松更改語言 :)
解決方案:
/**
* Get a random number between a range and exclude some numbers
*
* @param start start number
* @param end end number
* @param excludes list of numbers to be excluded
* @return value between {@code start} (inclusive) and {@code end} (inclusive)
*/
private int getRandomWithExclusion(int start, int end, List<Integer> excludes) {
Collections.sort(excludes); // this method only works with sorted excludes
int random = start + new Random().nextInt(end - start + 1 - excludes.size());
for (int exclude : excludes) {
if (random < exclude) {
break;
}
random++;
}
return random;
}
試試這個:
public static int GetRandomNumber(int Min, int Max, int[] ExcludedNumbers)
{
Random randomGenerator = new Random();
int currentNumber = randomGenerator.Next(Min, Max + 1);
while (ExcludedNumbers.Contains(currentNumber))
{
currentNumber = randomGenerator.Next(Min, Max + 1);
}
return currentNumber;
}
下面是它的用法示例:
int randomNumber = GetRandomNumber(1, 100, new int[] { 5, 7, 17, 23 });
編輯:僅適用於 Unity3D,我不知道 Random 是 Unity 的一個類。 它仍然可能對某人有幫助,所以我會把它留在這里。
我來晚了回答這個問題,但讓我們為對話做出貢獻。 這是我對已知的 Random.range(x,y) 的擴展,沒有列表或更復雜的東西:
public static int RandomExceptList(int min, int max, int[] forbiddenElements)
{
bool numberAllowed = true;
for(int i=0;i<forbiddenElements.Length;i++)
{
if(forbiddenElements[i]<min || forbiddenElements[i]>max)
{
Debug.Log("All forbidden numbers have to be inside given range.");
return min;
}
for (int j=i+1; j<forbiddenElements.Length;j++)
{
if(forbiddenElements[i]==forbiddenElements[j])
{
Debug.Log("Forbidden numbers have to be different between each other.");
return min;
}
}
}
if (max<min)
{
Debug.Log("Minimum limit has to be lower than maximum limit...");
return min;
}
if (forbiddenElements.Length>(max-min))
{
Debug.Log("You can't forbid so many numbers.");
return min;
}
if (forbiddenElements.Length>=1)
{
//this part here checks indefinitely for an allowed randomly generated number (outside "forbiddenElements" array). Eventually it will find it and return it and therefore terminate the loop.
while(true)
{
numberAllowed=true;
int r = Random.Range(min,max+1);
for(int i=0;i<forbiddenElements.Length;i++)
{
if (r==forbiddenElements[i])
numberAllowed=false;
}
if(numberAllowed)
return r;
}
}
else
{
int r = Random.Range(min,max+1);
return r;
}
}
請注意,在這種情況下,您必須始終輸入 forbiddenElements 參數,即使它是一個空數組。 Random.range 不使用數字池中的上限,所以我添加了“max+1”。 希望這可以幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.