Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何生成不能是列表中的值的随机整数<;int>;?_C#_.net_Windows Runtime - Fatal编程技术网

C# 如何生成不能是列表中的值的随机整数<;int>;?

C# 如何生成不能是列表中的值的随机整数<;int>;?,c#,.net,windows-runtime,C#,.net,Windows Runtime,我试着做以下几点 假设我有一个列表,我想在一个特定的范围内生成一个新的int,但是这个值不能在列表中定义 List<int> PredefinedIntsList = new List<int>() { 1, 3, 4, 8, 9 }; Random rnd = new Random(); int NewRandomValue = rnd.Next(0, 10); List PredefinedIntsList=newlist(){1,3,4,8,9}; 随机rnd=新

我试着做以下几点

假设我有一个列表,我想在一个特定的范围内生成一个新的int,但是这个值不能在列表中定义

List<int> PredefinedIntsList = new List<int>() { 1, 3, 4, 8, 9 };
Random rnd = new Random();
int NewRandomValue = rnd.Next(0, 10);
List PredefinedIntsList=newlist(){1,3,4,8,9};
随机rnd=新随机();
int NewRandomValue=rnd.Next(0,10);
接下来(显然)会出现1、3、4、8或9。但我只希望它返回2、5、6、7或10


有什么想法吗?

试试看是否可以使用List类的contains()方法。。。简单的解决方案是只生成值并检查包含和拒绝列表中已经存在的值,直到得到一个不包含的值。另外,使用Set类可能更合适,因为一个集合不能包含两个相等的元素。

您需要做的是从另一个集合中采样。假设P是您预定义的属性列表,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);

        }

    }
}
接下来(显然)会出现1、3、4、8或9。但我只想要它 返回2、5、6、7或10

显然不是,它将返回0、1、2、3、4、5、6、7、8或9:p的值。如果希望包含10而不是0,则需要
。下一步(1、11)

有两种选择可以起作用:要么尝试生成值直到成功,要么如果范围足够小,生成范围,标记无法拾取的元素,并将它们排序到最后一个,然后在[0..PossibleTopickeElementsCount]之间随机拾取

第一种方法如下所示:

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;
        }
    }
}
公共静态类扩展
{
公共静态int Next(此随机,
包括,
int maxExclusive,
IList值)
{
//如果值包含
//重复值。
var dic=数值。TODICTIONAL(val=>val);
//这可以进入永久循环,
//想一想。
对于(;;){
var randomNumber=random.Next(minInclusive,maxExclusive);
如果(!dic.ContainsKey(随机数))
返回随机数;
}
}
}
第二种方法是这样的,但它只是给你一个想法:

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.
    }
}
公共静态类扩展
{
类规范化对
{
公共int值{get;set;}
公共PairStatus状态{get;set;}
公共规范化对(int值){
价值=价值;
}
公共枚举对状态{
自由的
不免费
}
}
私有静态随机_internalRandom=新随机();
公共静态int Next(此随机,
包括,
int maxExclusive,
IList值)
{
var元素=maxExclusive-minInclusive;
var normalizedArr=新的NormalizedPair[元素];
var normalizedMiniInclusive=0;
var normalizedMaxExclusive=maxExclusive-minInclusive;
var normalizedValues=值
.选择(x=>x-minInclusive)
.ToList();
对于(var j=0;jy.Status==NormalizedPair.PairStatus.Free)//仅获取自由元素
.OrderBy(y=>\u internalRandom.Next())//洗牌自由元素
.Select(y=>y.Value+minInclusive)//项目正确的值
.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();
}
public static int Next2(此随机,
包括,
int maxExclusive,
IList值)
{
var rangeSet=新哈希集(
可枚举范围(
包括,
maxExclusive-minInclusive);
//消除杂音
rangeSet.ExceptWith(新哈希集(值));
//这可以用替换掉
//耶茨洗牌算法
返回rangeSet.OrderBy(x=>\u internalRandom.Next())
.First();
}

一如既往,林克是你的朋友:

[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);
} 
[TestMethod]
公开测试()
{
var except=新[]{1,2,3,5};
GetRandomException(1,5,Exception).Should()应该是(4);
}
私有静态int GetRandomExcept(int minValue、int maxValue、IEnumerable except)
{
返回GetRandoms(minValue,maxValue).Except(Except).First();
}
私有静态IEnumerable GetRandoms(int-minValue,int-maxValue)
{
var random=新的random();
while(true)收益率返回random.Next(minValue,maxValue);
} 
请记住,您永远不应该调用
GetRandoms().ToArray()
.Max()
.OrderBy()
等等,因为您将得到一个无休止的循环并永远生成随机数


不过,您可以调用
GetRandoms().Take(10).ToArray()
来获取数组中接下来的10个随机整数

与其写逻辑来确定是否已经选择了随机数,我更愿意生成第二个列表,其中的项目以随机顺序排列

这对LINQ来说很容易做到

var originalList = new List<int>() { 1, 3, 4, 8, 9 };
Random rnd = new Random();
var secondList = originalList.OrderBy(x=>rnd.NextDouble());

这是问“我如何随机洗牌数字”的一种迂回方式。一个非常常见的问题。在这种情况下,只需从一个包含10个整数的列表中随机选取一个元素,减去不需要的整数,然后将其从列表中删除,这样就不能再次选取该元素。
var originalList = new List<int>() { 1, 3, 4, 8, 9 };
Random rnd = new Random();
var secondList = originalList.OrderBy(x=>rnd.NextDouble());
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());
    }
  }