我试图做以下事情。
假设我有一个List,我想在特定范围内生成一个新的int,但是该值不能在List中定义。
List<int> PredefinedIntsList = new List<int>() { 1, 3, 4, 8, 9 };
Random rnd = new Random();
int NewRandomValue = rnd.Next(0, 10);
rnd.Next(显然)提出1,3,4,8或9.但我只想让它返回2,5,6,7或10。
有什么想法吗?
答案 0 :(得分:2)
一如既往,LINQ是你的朋友:
[TestMethod]
public void RandomTest()
{
var except = new[] {1, 2, 3, 5};
GetRandomExcept(1, 5, except).Should().Be(4);
}
private static int GetRandomExcept(int minValue, int maxValue, IEnumerable<int> except)
{
return GetRandoms(minValue, maxValue).Except(except).First();
}
private static IEnumerable<int> GetRandoms(int minValue, int maxValue)
{
var random = new Random();
while (true) yield return random.Next(minValue, maxValue);
}
请记住,您永远不应该拨打GetRandoms().ToArray()
或.Max()
或.OrderBy()
等等,因为您将获得无限循环并永久生成randoms。
你可以做的是调用GetRandoms().Take(10).ToArray()
来获取数组中的下10个随机整数。
答案 1 :(得分:0)
尝试检查是否可以使用List类的contains()方法...简单的解决方案是生成值并检查包含和拒绝List中已有的值,直到得到的值不是。另外,使用Set Class可能更合适,因为set不能包含两个相等的元素。
答案 2 :(得分:0)
您需要从其他套装中做样品。假设 P 是您的预定义IntsList,A是{1,2 ... 9}。 您需要创建一个列表 N = A-P 。您将从这组数字中随机抽样。我想它可以写得更优雅,但见下面的例子。
class Program
{
static void Main(string[] args)
{
List<int> predefinedIntsList = new List<int>() { 1, 3, 4, 8, 9 };
Random rnd = new Random();
List<int> newIntsList = new List<int>();
int upperBound = 10;
for (int i = 0; i < upperBound; i++)
{
if (!predefinedIntsList.Contains(i))
{
newIntsList.Add(i);
}
}
for (int i = 0; i < 20; i++)
{
int newRandomValueIndex = rnd.Next(0, newIntsList.Count);
int newRandomValue = newIntsList[newRandomValueIndex];
Console.WriteLine(newRandomValue);
}
}
}
输出
2
0
6
7
5
5
5
7
0
7
6
6
5
5
5
0
6
7
0
7
答案 3 :(得分:0)
rnd.Next(显然)提出了1,3,4,8或9.但我只想要它 返回2,5,6,7或10。
显然不是,它将返回0,1,2,3,4,5,6,7,8或9的值:P。如果您想要包含10而不是0,则需要.Next(1, 11)
有两种选择可以使用:尝试生成值,直到成功,或者范围足够小,生成范围,标记无法拾取的元素,并将它们排序为最后一个,然后选择在[0..possibleToPickElementsCount]
之间随机第一种方法看起来像这样:
public static class RandomExtensions
{
public static int Next(this Random random,
int minInclusive,
int maxExclusive,
IList<int> values)
{
// this will crash if values contains
// duplicate values.
var dic = values.ToDictionary(val => val);
// this can go into forever loop,
// think about this a bit.
for(;;){
var randomNumber= random.Next(minInclusive, maxExclusive);
if(!dic.ContainsKey(randomNumber))
return randomNumber;
}
}
}
第二种方法就是这样,但它只是给你一个想法:
public static class RandomExtensions
{
class NormalizedPair
{
public int Value {get;set;}
public PairStatus Status {get;set;}
public NormalizedPair(int value){
Value = value;
}
public enum PairStatus {
Free,
NotFree
}
}
private static Random _internalRandom = new Random();
public static int Next(this Random random,
int minInclusive,
int maxExclusive,
IList<int> values)
{
var elements = maxExclusive - minInclusive;
var normalizedArr = new NormalizedPair[elements];
var normalizedMinInclusive = 0;
var normalizedMaxExclusive = maxExclusive - minInclusive;
var normalizedValues = values
.Select(x => x - minInclusive)
.ToList();
for(var j = 0; j < elements; j++)
{
normalizedArr[j] = new NormalizedPair(j){
Status = NormalizedPair.PairStatus.Free
};
}
foreach(var val in normalizedValues)
normalizedArr[val].Status = NormalizedPair.PairStatus.NotFree;
return normalizedArr
.Where(y => y.Status == NormalizedPair.PairStatus.Free) // take only free elements
.OrderBy(y => _internalRandom.Next()) // shuffle the free elements
.Select(y => y.Value + minInclusive) // project correct values
.First(); // pick first.
}
}
或者,如果你喜欢套装:
public static int Next2(this Random random,
int minInclusive,
int maxExclusive,
IList<int> values)
{
var rangeSet = new HashSet<int>(
Enumerable.Range(
minInclusive,
maxExclusive - minInclusive));
// remove gibberish
rangeSet.ExceptWith(new HashSet<int>(values));
// this can be swapped out with
// yates shuffle algorithm
return rangeSet.OrderBy(x => _internalRandom.Next())
.First();
}
答案 4 :(得分:0)
不是编写逻辑来确定是否已经选择了随机数,而是选择以随机顺序生成第二个列表。
使用LINQ
很容易var originalList = new List<int>() { 1, 3, 4, 8, 9 };
Random rnd = new Random();
var secondList = originalList.OrderBy(x=>rnd.NextDouble());
对rnd.NextDouble
的调用返回OrderBy
方法用于对每个int值进行排序的随机种子。
当我需要多次运行思考随机项目时,每次走列表时都会使用新的排序顺序,我将使用Queue
来存储项目。然后根据需要将项目出列。当队列为空时,是时候重新填充了。
private Queue<int> _randomizedItems;
private void RandomTest()
{
var originalList = new List<int>() { 1, 3, 4, 8, 9 };
Random rnd = new Random();
var temp = originalList.OrderBy(r=>rnd.NextDouble());
_randomizedItems = new Queue<int>(temp);
while (_randomizedItems.Count >0)
{
MessageBox.Show(_randomizedItems.Dequeue().ToString());
}
}