【问题标题】:check if 2d array contains value on second spot检查二维数组是否在第二个位置包含值
【发布时间】:2017-05-06 10:35:21
【问题描述】:

我有一个我正在创建的彩票的二维数组。基本上它是一组 2 个整数: int[,] coupon = new int[rowAmount, numAmount]; 其中rowAmount 是行数,numAmount 是该行中的数字数。

现在我需要为每一行选择数字,但是在特定行中可能没有重复的数字。

        for (int r = 0; r < rowAmount; ++r)
    {
        for (int n = 0; n < numAmount; ++n)
        {
            userNum = lotRng.Next(1, numAmount * rngMult);
            while (COUPON CONTAINS DUPLICATE NUMBER ON SECOND SPOT )
            {
                userNum = lotRng.Next(1, numAmount * rngMult);
            }
            coupon[r, n] = userNum;
        }                    
    }

我的问题是 while 部分,我不知道如何检查 coupon 是否在第二个插槽(numAmount 插槽)上包含 userNum。对于列表和我以前只做list.Contains() 的东西,但这似乎在这里不起作用。

【问题讨论】:

  • 什么是lotRng?
  • 只是随机的:Random lotRng = new Random();
  • @GustavoA。 while (coupon[r, n] == userNum) {} 还是我误解了你的问题?
  • @Sebi the coupon[r..] 是正确的,但是,我需要检查 n 处的所有值,假设我在这一行有 9 个值,我需要确保没有这 9 个值是否等于第 10 个值(userNum),如果这样的话?

标签: c# arrays visual-studio


【解决方案1】:

根据数组的大小优化性能是否有意义。

根据这种可能性,一种可能性是对数组进行排序并使用 Array.BinarySearch 。

您必须为此对数组进行排序。

https://msdn.microsoft.com/en-us/library/2cy9f6wb(v=vs.110).aspx

所以你有很多优化数据结构的可能性。

【讨论】:

    【解决方案2】:

    具有列表数组的解决方案是我最喜欢的解决方案之一。它与我的其他锯齿状数组非常相似,但速度更快 - 因为列表搜索最有效,而 Linq 搜索则不是。

    const int rowAmount = 1000;
    const int numAmount=1000;
    const int rngMult = 10;
    Random lotRng = new Random();
    var coupon = new List<int>[rowAmount];
    int userNum;
    
    for (int r = 0; r < rowAmount; r++)
    {
        coupon[r]= new List<int>();
        for (int n = 0; n < numAmount; ++n)
        {
            do userNum = lotRng.Next(1, numAmount * rngMult);
            while (coupon[r].Contains(userNum));
            coupon[r].Add(userNum);
        }
    }
    

    当然,如果需要,也可以使用列表列表(一种二维列表)。

    var couponLoL = new List<List<int>>();
    

    以下快速而肮脏的方式展示了一种将二维数组复制到列表的可能方式,但出于多种原因(循环、值类型的装箱),此处不推荐:

    var coupon= new int[rowAmount,numAmount];
    

    [..]

            do userNum = lotRng.Next(1, numAmount * rngMult);
            while (coupon.Cast<int>().ToList().Contains(userNum));
    

    在这种特殊情况下,它的意义就更小了,因为这将在整个二维数组中查找双精度值。但值得了解如何从 2D 转换为 1D 数组(然后在列表中)。

    【讨论】:

      【解决方案3】:

      二维交错数组的解决方案:如果你想在 C# 中访问行和列,交错数组非常方便,除非你非常关心数组在内部存储的效率,否则交错数组是强烈推荐。

      锯齿状数组只是数组的数组。

      const int rowAmount = 1000;
      const int numAmount=1000;
      const int rngMult = 10;
      int userNum;
      Random lotRng = new Random();
      var coupon = new int[rowAmount][];
      for (int r = 0; r < rowAmount; r++)
      {
          coupon[r] = new int[numAmount];
          for (int n = 0; n < numAmount; ++n)
          {
              do userNum = lotRng.Next(1, numAmount * rngMult);
              while (Array.Exists(coupon[r], x => x == userNum));
      
              coupon[r, n] = userNum;
          }
      }
      

      上述函数 Array.Exists 仅适用于 1 维,这里就足够了,不需要 Linq。与上面的 Linq 方法 .Any 相同:

              while (coupon[r].Any(x => x == userNum));
      

      如果您必须在二维中搜索一个双精度值,您将需要更多的循环,但仍然在嵌套循环级别上比没有这个要少。

      Linq 很优雅,但通常不是最快的方法(但您必须处理数百万大小的非常大的数组才能做到这一点)。

      有关使用 Linq 的其他可能性,请在此处查看示例: How to use LINQ with a 2 dimensional array

      另一个想法是创建大小为 rowAmount*numAmount 的一维数组。 它需要一点思考,但允许最简单和最快的搜索访问。

      【讨论】:

        【解决方案4】:

        数组中有循环的解决方案。不优雅,但您可以用自己的方法重构搜索循环以使其看起来更好。但作为第二点,在这种情况下,如图所示的线性搜索也不是一个真正快速的解决方案。

        只有 2 个 for 循环的内部部分,而不是完整的代码(如我在这里的其他答案):

        bool foundDup;
        do
        {
            userNum = lotRng.Next(1, numAmount * rngMult);
            foundDup = false;
            for (var x = 0; x < coupon.GetLength(1); x++) //Iterate over second dimension only
                if (coupon[r, x] == userNum)
                {   foundDup = true;
                    break;
                }
        } while (foundDup);
        coupon[r, n] = userNum;
        

        在本题的特殊语境下,可以优化循环:

        for (var x = 0; x < n; x++)
        

        【讨论】:

          【解决方案5】:

          正如您在评论中所说,您需要检查所有 n 个字段与您的新 userNum。您可以使用以下代码解决此问题:

          for (int r = 0; r < rowAmount; ++r)
          {
            for (int n = 0; n < numAmount; ++n)
            {
              userNum = lotRng.Next(1, numAmount * rngMult);
              
              for (int x = 0; x < coupon.GetLength(1); x++) //Iterate over your second dimension again
              {
                while (coupon[r,x] == userNum)
                {
                  userNum = lotRng.Next(1, numAmount * rngMult);
                }
              }
              coupon[r, n] = userNum;
            }
          }
          

          【讨论】:

          • 对不起。但对我来说,这段代码看起来好像不起作用,并且有一个严重的缺陷:内部循环是错误的一面。例如:新发现的 x=100 的编号可能是 x=99 的两倍,因此之前对索引 99 的测试毫无价值。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-06-13
          • 1970-01-01
          • 2018-07-10
          • 1970-01-01
          • 1970-01-01
          • 2015-12-08
          相关资源
          最近更新 更多