【问题标题】:Linq group by multiple columns with anonymous columnLinq 由多个具有匿名列的列分组
【发布时间】:2013-06-17 13:02:02
【问题描述】:

我不知道如何正确表达这个问题,但我有:

            var groups = data.GroupBy(x => new {x.EntityId, x.StartLocal = new {
                var stamp = x.StartLocal;
                stamp = stamp.AddHours(-(stamp.Hour % hours));
                stamp = stamp.AddMinutes(-stamp.Minute);
                stamp = stamp.AddMilliseconds(-stamp.Millisecond);
                return stamp;
            }})
.Select(...)
            .ToList();

这不起作用(语法错误)。我首先想按entityId 分组,然后按名为StartLocal 的字段的小时分组,就像我每2 小时对结果进行分组一样:

Id = 1
     Hour = 2
     Hour = 4
Id = 2
     Hour = 2
...

像这样。

我需要填写的内容:

        DO obj = new DO
        {
            EntityId = pp.EntityId,
            EntityCode = pp.EntityCode,
            StartLocal = pp.StartLocal,
            Volume = pp.Volume,
        };

Volume 是需要聚合的。所以基本上 1000 个这些 DO 以数组的形式出现,然后它们被 EntityId 分割,然后被 StartLocal 的小时数分割……体积被聚合了 x 小时的价值,并且创建了相同的 DO……但现在很多少一些。

【问题讨论】:

  • 那么“错误的语法”是错误信息吗?
  • 与如何声明匿名类型无关,但它不值得引用,因为真正的问题是我不知道如何声明第二列来分组,其中包含的不仅仅是x.属性。
  • 根据您想要的输出,您似乎只想对 ID 进行分组,而不是其他任何东西,并且您的时间操作都属于 GroupBy 之后的 Select。您是否真的想要深度为 3 的树,而不仅仅是深度为 2 的树。如果是这样,如果您相应地修改所需的输出将会有所帮助。

标签: c# linq group-by aggregate


【解决方案1】:

您似乎想要这样的东西:

var groups = data.GroupBy(x => 
    {
        var stamp = x.StartLocal;
        stamp = stamp.AddHours(-(stamp.Hour % hours));
        stamp = stamp.AddMinutes(-stamp.Minute);
        stamp = stamp.AddMilliseconds(-stamp.Millisecond);
        return new { x.EntityId, StartLocal = stamp };
    });

或者更简单地说:

var groups = data.GroupBy(x => new 
    { 
        x.EntityId, 
        StartLocal = new DateTime(
            x.StartLocal.Year, 
            x.StartLocal.Month, 
            x.StartLocal.Day, 
            x.StartLocal.Hour % hours, 0, 0)
    });

这两个都给出了StartLocal 向下舍入到一个小时。如果你只想要一个小时,你可以这样做:

var groups = data.GroupBy(x => new { x.EntityId, x.StartLocal.Hour % hours });

【讨论】:

  • 嗨 pswg 看来您的第一个解决方案不是按 entityId 分组,而第二个解决方案没有提供细粒度控制,例如我想在一个小时内作为 int 传递并让它按那个分组.
  • @MuhammadA 第一个解决方案确实按EntityId 分组,(参见代表new { x.EntityId, x.StartLocal = stamp } 的最后一行)。第二个给出x.StartLocal,四舍五入到小时。如果你想要的只是一个小时作为int,请参阅我的最新更新。
【解决方案2】:

您真正需要的是对GroupBy 的调用,而不是对复杂对象的单个调用分组。

var query = data.GroupBy(item => item.EntityId)
    .Select(group => group.GroupBy(item => item.StartLocal));

这将为您提供深度为 3 的树,而不是两个,或者换句话说,组的组。

【讨论】:

    【解决方案3】:

    你应该解释你为什么要在更高的层次上做。可能还有其他(更好的)方法可以完成您正在尝试做的事情。

    从您的操作来看,在我看来您只是在尝试按项目的 ID 以及开始的日期和时间对项目进行分组。您无需尝试创建单个 DateTime 对象来表示日期和小时,只需分别获取组件即可。此外,您的查询提供程序可能不支持复杂的选择器,这看起来不像 LINQ to objects 查询。

    这样做:

    var groups = data.GroupBy(x => new
        {
            x.EntityId,
            StartDate = x.StartLocal.Date,
            StartHour = x.StartLocal.Hour,
        })
        .Select(...)
        .ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-16
      • 2011-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多