【问题标题】:LINQ query with multiple aggregates具有多个聚合的 LINQ 查询
【发布时间】:2010-09-14 08:34:36
【问题描述】:

如何创建等效的 Linq To Objects 查询?

SELECT MIN(CASE WHEN p.type = "In" THEN p.PunchTime ELSE NULL END ) AS EarliestIn,
       MAX(CASE WHEN p.type = "Out" THEN p.PunchTime ELSE NULL END ) AS LatestOUt
FROM Punches p

【问题讨论】:

    标签: linq .net-3.5 linq-to-objects


    【解决方案1】:

    产生最小值和最大值的单个枚举(以及您想要放入其中的任何其他聚合)。这在 vb.net 中要容易得多。

    我知道这不能处理空箱。这很容易添加。

        List<int> myInts = new List<int>() { 1, 4, 2, 0, 3 };
        var y = myInts.Aggregate(
            new { Min = int.MaxValue, Max = int.MinValue },
            (a, i) =>
            new
            {
               Min = (i < a.Min) ? i : a.Min,
               Max = (a.Max < i) ? i : a.Max
            });
        Console.WriteLine("{0} {1}", y.Min, y.Max);
    

    【讨论】:

    • 它有点手动,但对我来说已经足够了。有趣的是,当您分解 linq 时,您如何快速返回到 foreach 外观的语法快捷方式。
    • 讽刺的是,不是吗? foreach 只是一个语法快捷方式。
    【解决方案2】:

    您无法在 vanilla LINQ to Objects 中有效地选择多个聚合。当然,您可以执行多个查询,但这可能效率低下,具体取决于您的数据源。

    我有一个框架来解决这个问题,我称之为“Push LINQ”——这只是一种爱好(对我和 Marc Gravell 来说),但我们相信它工作得很好。它作为MiscUtil 的一部分提供,您可以在my blog post on it 中了解它。

    这看起来有点奇怪 - 因为您将希望结果的位置定义为“期货”,然后通过查询推送数据,然后检索结果 - 但是一旦您了解它,就可以了。我很想听听你如何使用它 - 如果你使用它,请给我发邮件至 skeet@pobox.com。

    【讨论】:

    • 谢谢乔恩。到目前为止,关于 Linq 最困难的部分之一是弄清楚你能做什么和不能做什么。一旦我对标准方法更加熟悉了,我一定会看看你的 Push 技术。
    【解决方案3】:

    可以使用 LINQ-to-Objects 进行多个聚合,但有点难看。

    var times = punches.Aggregate(
        new { EarliestIn = default(DateTime?), LatestOut = default(DateTime?) },
        (agg, p) => new {
            EarliestIn = Min(
                agg.EarliestIn,
                p.type == "In" ? (DateTime?)p.PunchTime : default(DateTime?)),
            LatestOut = Max(
                agg.LatestOut,
                p.type == "Out" ? (DateTime?)p.PunchTime : default(DateTime?)) 
        }
    );
    

    您还需要 DateTime 的 Min 和 Max 函数,因为这些不是可用的标准。

    public static DateTime? Max(DateTime? d1, DateTime? d2)
    {
        if (!d1.HasValue)
            return d2;
        if (!d2.HasValue)
            return d1;
        return d1.Value > d2.Value ? d1 : d2;
    }
    public static DateTime? Min(DateTime? d1, DateTime? d2)
    {
        if (!d1.HasValue)
            return d2;
        if (!d2.HasValue)
            return d1;
        return d1.Value < d2.Value ? d1 : d2;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 2014-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多