使用linq查询类的平衡值

时间:2017-09-21 14:28:16

标签: c# linq

我有一个类,有几个从0到1的标准化双精度数。 这个类有大约100.000个条目,看起来像这样:

class Data
{
    public double Norm1 { get; set; }
    public double Norm2 { get; set; }
    public double Norm3 { get; set; }
    public double Norm4 { get; set; }
}

条目已添加到<List>。 现在我必须在此列表中找到最佳平衡条目。

在moement我使用循环来找到这个最佳平衡值。 循环看起来像这样:

double nor = 0.01;
List<Data> tempList = null;
List<Data> lasttempList = null;
do
{
    tempList = null;
    tempList = new List<Data>(DATALIST);
    tempList = tempList
                   .Select(i => i)
                   .Where(j => 
                       j.Norm1 >= nor 
                       && j.Norm2 >= nor 
                       && j.Norm3 >= nor 
                       && j.avgN >= nor 
                       && j.Norm4 >= nor
                   ).ToList();

    if (tempList.Count() > 0)
        lasttempList = new List<Data>(tempList);

    nor = nor + 0.01;

} while (tempList.Count() > 1 && nor <= 0.99);

最后,我正在检查tempList或lasttempList以查找条目。

有没有人知道如何在没有循环的情况下完成这项工作并只使用Linq?

1 个答案:

答案 0 :(得分:0)

我不确定自己是朝着正确的方向前进,但让我试一试。我会假设:

  1. DATALIST是在while循环期间组成(未变异)的输入。

  2. 您希望最佳平衡值(满足谓词)恰好为1。

  3. 我们可以为列表中的每个Data计算一个限制值,并创建具有相同限制值的组。这为我们打开了两个场景。

    1. 我们只有一个单值组。

    2. 我们有几个小组,每个小组都有完全单一的值。

    3. Se首先计算限制。您检查.01,.02,。03等。 所以我们可以写这样的东西来计算Data的限制。

      private static double ComputeLimit(Data data)
      {
          // all of the original values from the data object
          // unified to two deciaml digits after the dot.
          var values = new [] { data.Norm1, data.Norm2, data.Norm3, data.Norm4, data.avgN }
             .Select(x => Math.Floor(x * 100) / 100); 
      
         // the limit it self can be represented as the smallest number in the array
         // if we need all of the values to be greater then some limit
         // we ca assume that the smallest number is actually the limit of the data object
         var limit = values.Min();
      
         return limit;
      }
      

      现在让我们创建群组。每个组都将包含特定限制内的所有数字。

      var groups = DATALIST.GroupBy(ComputeLimit);
      
      // using .Skip(1).Any() instead of .Count() because it is faster
      // to determ if the group has exactly one item
      // NOTE: If there is more then one group having exactly one item
      // the result will be the group with the lowest limit
      // also the ordering may be OK for you, if you need to keep the result consisted
      var bestBalanced = groups
               .Where(x => x.Skip(1).Any() == false)
               .OrderBy(x => x.Key)
               .First()
               .Single()