Linq GroupBy将每个空值作为一个组

时间:2015-02-27 08:47:25

标签: c# linq group-by

我有一个可以为null的int属性“GroupId”的对象。

使用此对象的List,我想在此“GroupId”上执行GroupBy。但是如果我这样做,所有空值都将形成一个组。

示例:

对象1:GroupId:NULL

对象2:GroupId:NULL

对象3:GroupId:1

对象4:GroupId:1

对象5:GroupId:2

对象6:GroupId:2

MyList.GroupBy(f => f.GroupId, key => new {Object = key});

我会得到3组。

如何获得4组呢?每个NULL值的组...

2 个答案:

答案 0 :(得分:9)

这可能是最短的解决方案:

var grouped = MyList.GroupBy(f => f.GroupId != null ? (object)f.GroupId : new object(), key => new { Object = key });

请注意,组的“密钥”将为object类型。对于null元素,我创建了一个新的“空”object。对象的相等比较器将使它们全部不同。对于非空数字,我只需将它们放在一个对象中。盒装整数维持等式运算符。所以:

new object().Equals(new object()) == false // always

((object)1).Equals((object)1) == true // always

((object)1).Equals((object)2) == false // always

更正确的解决方案是实施IEqualityComparer<int?>

public class MyComparer : IEqualityComparer<int?> {
    public bool Equals(int? x, int? y) {
        if (x == null || y == null) {
            return false;
        }

        return x.Value == y.Value;
    }

    public int GetHashCode(int? obj) {
        return obj.GetHashCode(); // Works even if obj is null :-)
    }
}

并使用它:

var grouped2 = MyList.GroupBy(f => f.GroupId, key => new { Object = key }, new MyComparer());

答案 1 :(得分:2)

可以在没有拳击的情况下使用的Generic Comparer。

public class NullableComparer<T> : IEqualityComparer<T?>
        where T : struct
{
    public bool Equals(T? x, T? y)
    {
        if (x == null || y == null)
        {
            return false;
        }

        return x.Equals(y);
    }

    public int GetHashCode(T? obj)
    {
        return obj.GetHashCode();
    }
}

然后你会像:

一样使用它
// where GroupId as a nullable Guid 
var grouped = MyList.GroupBy(f => f.GroupId, new NullableComparer<Guid>());