使用linq计算组

时间:2016-09-24 17:55:59

标签: c# linq

我有一个名为模拟结果的对象。

 public SimulationResult
 {
        public Horse Winner {get;set;}
        public Horse Second {get;set;}
        public Horse Third {get;set;}
        public Horse Fourth {get;set;}
  }

  public Horse
  {
        public Guid Id{get;set;}
  }

所以,我有50000个SimulationResult的列表。如何确定前50个最常见的结果。

我尝试使用LINQ groupBy,但是HorseId出现在每个对象中,并且它不允许多次出现一个值。

EDIT 对不起,以为很清楚。 所以我们共有8匹马。说马id是1-8。

因此在模拟结果1中,获胜者为1,第二名为2,第三名为3,第四名为4.

在模拟结果2中,第一个是5,第二个是6,第三个是7,第四个是8.

在模拟结果3中,第一个是1,第二个是2,第三个是3,第四个是4。

因此结果集1和结果集3相等。所以在这个样本中,获胜者1秒2第三名3第四名4是最常见的结果。

3 个答案:

答案 0 :(得分:3)

  

我尝试使用LINQ groupBy,但是HorseId出现在每个对象中,并且它不允许多次出现一个值。

如果你的意思是使用Grouping by Composite Keys中解释的匿名类型,虽然大多数时候我们可以让编译器推断出我们的名字,但我们总是(并且在这里有必要)明确地指定它们:

var topResults = simulationResults
    .GroupBy(r => new
    { 
        WinnerId = r.Winner.Id,
        SecondId = r.Second.Id,
        ThirdId = r.Third.Id,
        FourthId = r.Fourth.Id,
    })
    .OrderByDescending(g => g.Count())
    .Select(g => g.First()) // or new { Result = g.First(), Count = g.Count() } if you need the count
    .Take(50)
    .ToList();

答案 1 :(得分:1)

您问题的最简单答案:

class ExactResult {
    public String CombinedId { get; set; }
    public int Count { get; set; }
}
resultList.Select(l => {
    var combinedId = l.Winner.Id.ToString() + l.Second.Id.ToString() + l.Third.ToString() + l.Fourth.ToString();
    return new ExactResult() { CombinedId = combinedId), Count = l.Count(c => c.Winner.Id.ToString() + c.Second.Id.ToString() + c.Third.ToString() + c.Fourth.ToString();)}
}).OrderByDescending(e => e.Count).Take(50)

但答案毫无意义。如果您真正想要的是最有可能从一堆结果中获胜的4名获胜者,那么这不是解决问题的方法。这将与EXACT相同的4位获胜者展示最多的结果。 您可能正在寻找的是统计分析或传播。无论如何,事情比你实际要问的更复杂。

答案 2 :(得分:1)

也许这就是你要找的东西:

var q = (from x in mySimulationResultList
        group x by x into g
        let count = g.Count()
        orderby count descending
        select new { Value = g.Key, Count = count }).Take(50);

foreach (var x in q)
{
    Console.WriteLine($"Value: {x.Value.ToString()} Count: {x.Count}");
}

如果您想为Console.WriteLine提供有意义的输出,则需要覆盖ToStringHorse的{​​{1}}

您必须覆盖SimulationResult的{​​{1}}和Equals,如下所示:

GetHashCode

来源here(按查询分组)和here(将对象与对方进行比较)