【问题标题】:Select Max value from sublist with LINQ使用 LINQ 从子列表中选择最大值
【发布时间】:2010-12-03 19:44:41
【问题描述】:

如何编写一个 LINQ 查询,该查询将返回“值”类型的行,其中包含该日期的最大日期和最大值。它应该是 name = "Correct" 的行

我最后写了一个查询,它工作正常,只是想找到一个正确的方法。

提前致谢

public class MeasurePoint
{
    public int No { get; set; }
    public string Weight { get; set; }
    public List<Values> Vals { get; set; }
}

public class Values
{
    public string Name { get; set; }
    public int Val { get; set; }
    public DateTime Date { get; set; }
}

public static class Test
{
    public static void Calc()
    {
        var mps = new List<MeasurePoint>();

        mps.Add(new MeasurePoint()
        {
            No = 1,
            Vals = new List<Values>()
            {
                new Values(){Date = DateTime.Now.Date.AddDays(1), Name = "testas", Val = 1},
                new Values(){Date = DateTime.Now.Date.AddDays(2), Name = "testas", Val = 5},
                new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 15}
            }});
        mps.Add(new MeasurePoint()
        {
            No = 2,
            Vals = new List<Values>()
            {
                new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 11},
                new Values(){Date = DateTime.Now.Date.AddDays(2), Name = "Correct", Val = 55},
                new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 15}
            }
        });
        mps.Add(new MeasurePoint()
        {
            No = 3,
            Vals = new List<Values>()
            {
                new Values(){Date = DateTime.Now.Date.AddDays(1), Name = "testas", Val = 111},
                new Values(){Date = DateTime.Now.Date.AddDays(2), Name = "testas", Val = 52},
                new Values(){Date = DateTime.Now.Date, Name = "testas", Val = 15}
            }
        });

        mps.Add(new MeasurePoint()
        {
            No = 4,
            Vals = new List<Values>()                      
        });

        var x = mps.ElementAt(0).Vals.Union(mps.ElementAt(1).Vals).Union(mps.ElementAt(2).Vals);
        var z = x.Where(p => p.Date == x.Max(d => d.Date)).MaxBy(t=>t.Val);

        //One more way I've found
        var ttt = mps.SelectMany(p => p.Vals).GroupBy(t=>t.Date).MaxBy(r=>r.Key).MaxBy(g=>g.Val);
    }

【问题讨论】:

    标签: c# linq


    【解决方案1】:
    var max = mps.SelectMany(x => x.Vals)
        .Aggregate((a, x) => (x.Date > a.Date) ||
                             ((x.Date == a.Date) && (x.Val > a.Val)) ? x : a);
    

    【讨论】:

    • @Martynas: SelectMany 简单地将您的原始集合“扁平化”为一个序列,其中包含来自所有Vals 集合的所有Values 对象MeasurePoint 对象。 Aggregate 然后逐步完成展平序列,将每个元素与最大值进行比较(到目前为止)。如果当前元素大于最大值,则它成为新的最大值。处理完所有元素后,将返回最大值。
    【解决方案2】:

    试试这个

    var result = mps.Where(m => m.Vals.Count > 0)
        .SelectMany(m => m.Vals
            .OrderByDescending(v => v.Date)
            .Take(1), (m, v) => new {m.No, v.Date, v.Name, v.Val});
    

    编辑 - 这是一个新版本,因为问题变得更加清晰

    var result = mps.Where(m => m.Vals.Count > 0)
        .SelectMany(m => m.Vals)
        .OrderByDescending(v => v.Date)
        .ThenByDescending(v => v.Val).Take(1);
    

    【讨论】:

    • 我,如果我需要按最大日期查找记录,这将是正确的,但它还需要找到该日期的最大“Val”。但是你的想法很好:) 谢谢
    • 酷 :) 将尝试所有这些,看看哪一个提供最佳性能:)
    • 我接受了 Lukeh 的回答,因为它提供了更好的性能。
    【解决方案3】:

    如果是IObservable&lt;T&gt;同时GroupBy()返回IEnumerable&lt;T&gt;的方法,如何调用MaxBy()

    【讨论】:

    • 嘿 :) 我已经安装了 Reactive Linq Extensions 并且完全忘记了它们 :)
    • @Martynas:请在您的帖子中提及这一点,以使其更清楚:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多