按日期时间间隔对对象进行分组

时间:2018-09-08 14:18:09

标签: c# linq

我有一个用户列表及其注册日期。现在,我想按5分钟的间隔将用户的注册日期分组,如下所示:

Group 1
15:01
15:03
15:04

Group 2
15:06
15:06

Group 3
15:17

Group 4
15:59

我的问题是:为什么此解决方案给我正确的答案:

var users = GetUsers();
var interval = 5;

var registerInvervals = users.GroupBy(x => new
    {
        Month = x.Registered.Month,
        Day = x.Registered.Day,
        Hour = x.Registered.Hour,
        MinuteFrom = (x.Registered.Minute/interval)*interval,
        MinuteTo = (((x.Registered.Minute / interval) * interval) + 5)%61
    })
    .ToList();

但不是:

var users = GetUsers();
var interval = 5;

var registerInvervals = users.GroupBy(x => new GroupCriteria()
    {
        Month = x.Registered.Month,
        Day = x.Registered.Day,
        Hour = x.Registered.Hour,
        MinuteFrom = (x.Registered.Minute/interval)*interval,
        MinuteTo = (((x.Registered.Minute / interval) * interval) + 5)%61
    })
    .ToList();

class GroupCriteria
{
    public int Month { get; set; }
    public int Day { get; set; }
    public int Hour { get; set; }
    public int MinuteFrom { get; set; }
    public int MinuteTo { get; set; }
}

第二个解决方案返回7个组,每个组1个用户。

2 个答案:

答案 0 :(得分:3)

这是因为您没有为Equals类覆盖GetHashCodeGroupCriteria。调用GroupBy时,通过共享同一键将项目分组。在指定的情况下,键是您创建的对象,并且相等性是针对该实例定义的相等性。为GroupCriteria这样做时,它会通过默认定义的对象(对象的引用)检查对象的相等性。在为每个项目投影一个新对象时,引用将有所不同,并且组属于单个项目。

对于匿名对象(new {...}),等于(equals)比较字段并因此起作用。有关此行为的更多信息,请阅读Why does the Equals implementation for anonymous types compare fields?。正如格特在该问题的回答中所述:

  

匿名类型上的Equals和GetHashcode方法会覆盖从对象继承的方法,并根据属性的Equals和GetHashcode进行定义,因此,当且仅当它们的所有属性都相同时,相同匿名类型的两个实例才相等相等。

答案 1 :(得分:2)

通过相等性比较创建的实例。对于第一个示例中的匿名类型instances are equal if the fields are,但在第二个示例中,相等性是通过引用获得的,因此,具有相同属性值的两个实例不视为相等,因此最终位于不同的组中。