我的大脑今天正在融化,我想不出怎么做这么简单的代码。 numberList是一个由逗号分隔的数字字符串,如'2,34,10'等。当我请求一个随机数时,我需要检查字符串是否有数字,如果是,我想继续请求一个随机数,直到随机数绝对不在字符串中。我不知道我会采取什么样的循环来实现这个目的:
Random r = new Random();
public int RandomPos(int max) {
int i;
do {
i = r.Next(max) + 1;
}
while (!numberList.Contains(i.ToString()));
return i;
}
答案 0 :(得分:2)
我只是用文本而不是代码来解释,因为我现在懒得编写代码:
String.Split
将列表分成数组,然后(如果需要)将其解析为整数。Enumerable.Range(0, max).ToArray()
创建您可以选择的所有号码的列表。这样做的好处是,您无需随机选择内容并在可能无限但未真正实践的循环中重试。
string[] invalid = numberList.Split(", ");
var list = Enumerable.Range(0, max).Where(x => !invalid.Contains(x.ToString())).ToArray();
return list[r.Next(list.Count)];
答案 1 :(得分:1)
也许这就是你想要的?我使用了常规的while
,因为我觉得它们更容易阅读,我认为你唯一错的就是!
。
public int RandomPos(int max) {
int i = r.Next(max);
var intList = numberList.Split(',').ToDictionary<string,int>((n) => int.Parse(n));
while(intList.Contains(i))
{
i = r.Next(max);
}
return i;
}
假设我需要首先将numberList
拆分为如果它们在字符串中。这将使第三行看起来像:
答案 2 :(得分:1)
删除!
do
{
i = r.Next(max) + 1;
}
while (numberList.Contains(i.ToString()));
答案 3 :(得分:1)
试试这个:
static string invalidNumbers = "0,1,2,3,4,5";
static Random random = new Random();
static int Randomize()
{
var randomInt = random.Next(0, 10);
if (!invalidNumbers.Split(',').Contains(randomInt.ToString()))
{
return randomInt;
}
else
{
return Randomize();
}
}
答案 4 :(得分:1)
提供简单的答案,您不需要Split()。假设数字之间没有空格,相应地修改:
String modifiedNumberList = "," + numberList + ",";
do {
i = r.Next(max) + 1;
}
while (modifiedNumberList.Contains("," + i.ToString() + ","));
编辑:我相信BrokenGlass也是对的,你不应该从我的解决方案中删除“!”。
答案 5 :(得分:0)
@ Dave回复的修改:
static string invalidNumbers = "0,1,2,3,4,5";
static Random random = new Random();
static int Randomize()
{
var randomInt = random.Next(0, 10);
var splitString = invalidNumbers.Split(',');
while (splitString.Contains(randomInt.ToString()))
{
randomInt = random.Next(0, 10);
}
return randomInt;
}
答案 6 :(得分:0)
// if numberList is large then use HashSet<int> rather than a plain int[] array
int[] nums = numberList.Split(new[] { ',', ' ' },
StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
int i;
while (nums.Contains(i = r.Next(max) + 1));
return i;
(如果/ numberList
包含rng可能产生的所有可能值,您还应该添加一个检查以确保不会以无限循环结束。)
答案 7 :(得分:0)
有几种改进方法:
1)使用List<int>
或其他东西而不是字符串来让您的生活更轻松
2)如果max
很小(比如说<1000或者其他),则生成所有可能值的列表,随机排序,并从该列表中依次返回数字。
当“使用”数字的数量接近“max”时,您可能会在获得未使用的数字之前以非常长的循环结束。对于最大值超过几百的值,这实际上可能是重要的。在您的情况下,这可能是也可能不是问题。
答案 8 :(得分:0)
此代码将涵盖所有情况:
“1,2,3,4,5”......
private static int GetRandomNumber(string existingNumbers, int max)
{
string[] existingNumbersArray = existingNumbers.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
List<string> existingNumbersList = new List<string>();
foreach (string number in existingNumbersArray)
{
existingNumbersList.Add(number.Trim());
}
while (true)
{
Random rnd = new Random();
int value = rnd.Next(max);
if (!existingNumbersList.Contains(value.ToString()))
{
return value;
}
}
}
你甚至可以拿出这部分:
foreach (string number in existingNumbersArray)
{
existingNumbersList.Add(number.Trim());
}
while (true)
{
Random rnd = new Random();
int value = rnd.Next(max);
if (!existingNumbersList.Contains(value.ToString()))
{
return value;
}
}
因此每次调用GetRandomNumber函数时都不会调用它。
答案 9 :(得分:0)
.Split
将完成这项工作,以下代码也可以正常工作,只是为了好玩(替换代码中的行while (!numberList.Contains(i.ToString()));
,而不是检查{{1} }检查i.ToString()
加上开头和结尾。如果","+i.ToString()+","
之后有空格,则需要调整它:
","
答案 10 :(得分:0)
我对所有其他答案的补充..
const string invalidNumbers = "0,1,2,3,4,5";
Random random = new Random();
int value = 0;
List<int> tmpList = new List<int>();
foreach (var x in invalidNumbers.Split(','))
{
tmpList.Add(Int32.Parse(x));
}
do
{
value = random.Next(0, 10);
}
while (tmpList.Contains(value));
return value
答案 11 :(得分:0)
编辑:误解了第一篇文章的问题,无论如何,这是一个递归的解决方案。
将数字保留在列表中似乎更好,但是如果需要遵循您提出的格式,这里是:
const int MAX_ATTEMPTS = 10;
Random r = new Random();
string nlist = "2, 34, 10";
public int RandomPos(int max_val)
{
List<string> used = nlist.Replace(" ","").Split(',').ToList();
return _RandomPos(MAX_ATTEMPTS, max_val, used);
}
private int _RandomPos(int tl, int max, List<string> used)
{
if (tl <= 0)
throw new Exception("Could not generate random number. Too many tries.");
else
{
int rnum = r.Next(max);
if (!used.Contains(rnum.ToString()))
{
nlist += ", " + rnum.ToString();
return rnum;
}
else
return _RandomPos(tl - 1, max, used);
}
}
答案 12 :(得分:0)
我意识到有很多条目,但我没有看到任何一些不错的错误检查。话虽如此,这将提供一些东西:
-1
所以这里是:
public int RandomPos(int max)
{
// compile the list of numbers we need to disqualify
List<int> disqualified = numberList.Split(new[]{',',' '},StringSplitOptions.RemoveEmptyEntries).Select(n => int.Parse(n)).ToList();
// Nothing to check against, save the CPU cycles
if (disqualified.Count == 0)
return (new Random(DateTime.Now.Millisecond)).Next(max) + 1;
// make a list of everything that's possible for a choice
List<int> valid = Enumerable.Range(0, max).Where(r => !disqualified.Contains(r)).ToList();
// return either a valid result, or -1 if there are no valid results
return (valid.Count == 0 ? -1 : valid[(new Random(DateTime.Now.Millisecond)).Next() % valid.Count]);
}