LINQ查询按多个和顺序分组

时间:2012-02-12 21:11:56

标签: c# linq

我有以下数据结构:

public class Difference
{
    public Difference() { }
    public Differential Type { get; set; }
    public int Magnitude { get; set; }
}
public enum Differential
{
    low,
    middle,
    high
}

我可能有以下数据:

Magnitude      Type
4456           low
4456           low
4423           low
4421           low
1000           high
1000           high
1001           high
1560           middle
4456           low
4421           low

我试图返回一个数据集,这个数据集给出了 Count 数字相同的maginitudes及其类型但每种类型的顶部按计数的降序排列以上(按顺序)

价值 4456 类型:数量: 3

价值 1000 类型:计数: 2

价值 1560 类型:中间数量: 1

请注意4421在2的计数中是不是因为4456有更大的计数?

我想我已经接近但不太相似:

var query = (from value in differences
             group value by new {value.Magnitude, value.Type} into groupjoin
             select new
             {
                 Value = groupjoin.Key.Magnitude,
                 Type = groupjoin.Key.Type,
                 Count = groupjoin.Count()                                         
             })
            .OrderByDescending(v => v.Count)
            .ThenByDescending(v => v.Value).ThenByDescending(v => v.Type).ToList();

更新

基于道格拉斯下面的建议,我设法用以下方法实现它。我不太担心,如果有关系,我想尽可能返回First()一个(对于每种类型)。我只能通过循环来做到这一点:

var query = (from value in differences
                                 /*where value.type == Differential.low*/
                                 group value by new {value.Magnitude, value.Type} into groupjoin
                                 select new
                                 {
                                     Value = groupjoin.Key.Magnitude,
                                     Type = groupjoin.Key.Type,
                                     Count = groupjoin.Count()                                         
                                 });

                    var query2 = query.Where(g1 => !query.Any(g2 =>
                                    g2.Type == g1.Type &&
                                    g2.Count > g1.Count));

                    int highest = 0;
                    int lowest = 0;
                    int middle = 0;
                    foreach (var item in query2)
                    {
                        if (item.Type == Differential.high && item.Count > highest) 
                        {
                            oresult.numberOfHighHits = item.Count;
                            oresult.highTimeMagnitude = item.Value;
                        }
                        if (item.Type == Differential.low && item.Count > lowest)
                        {
                            oresult.numberOfLowHits = item.Count;
                            oresult.lowTimeMagnitude = item.Value;
                        }
                        if (item.Type == Differential.middle && item.Count > middle)
                        {
                            oresult.numberOfMiddleHits = item.Count;
                            oresult.middleTimeMagnitude = item.Value;
                        }
                    }

1 个答案:

答案 0 :(得分:3)

我保留了LINQ查询的第一部分,它给出了不同幅度类型对(及其计数)的分组:

var query = 
    from value in differences                                     
    group value by new {value.Magnitude, value.Type} into groupjoin
    select new
    {
        Value = groupjoin.Key.Magnitude,
        Type = groupjoin.Key.Type,
        Count = groupjoin.Count()                                         
    };

然后,我正在编写另一个LINQ,它接受第一个查询生成的所有分组,并且对于每个分组g1,检查是否存在任何其他具有相同分组的分组g2类型和更大的计数。这将确保仅返回具有最大类型计数的分组。在tie的情况下(同一类型的多个分组具有相同的最大计数),将返回所有顶级分组。

var query2 = query.Where(g1 => 
    !query.Any(g2 => 
        g2.Type == g1.Type && 
        g2.Count > g1.Count));

修改:要为每种类型返回单个结果,即使是关系,我们也可以向query2过滤器添加另一个条件,这样,如果两个分组具有相同的{ {1}} 相同的Type,然后挑选具有较大Count(原名为Value)的Magnitude。如果您希望选择较小的Value,请将>替换为<

这种方法会使查询结果具有确定性(而不是任意依赖于,例如,哪个分组首先出现在原始列表中)。

var query2 = query.Where(g1 => 
    !query.Any(g2 => 
        g2.Type == g1.Type && 
        (g2.Count > g1.Count || (g2.Count == g1.Count && g2.Value > g1.Value))));