Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq GroupBy with each null value as a group

Tags:

c#

linq

group-by

I have an object with a nullable int property "GroupId".

With a List of this object, I would like to do a GroupBy on this "GroupId". But if I do it, all the null values will form a group.

Example :

Object 1 : GroupId : NULL

Object 2 : GroupId : NULL

Object 3 : GroupId : 1

Object 4 : GroupId : 1

Object 5 : GroupId : 2

Object 6 : GroupId : 2

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

I will get 3 groups.

How can I get 4 groups instead ? A group for each NULL value...

like image 577
Gab Avatar asked Feb 27 '15 08:02

Gab


People also ask

How do I Group by a specific value in LINQ?

The GroupBy method is the same as the SQL group by statement. By using the LINQ GroupBy () syntax we can group the data based on the particular value of the key. How group by query works in LINQ? In GroupBy method, it returns a collection that has a specific key and with the inner collection with a base of the key field value.

What is LINQ groupby method in C #?

What is Linq GroupBy Method in C#? The Linq GroupBy in C# belongs to the Grouping Operators category and exactly does the same thing as the Group By clause does in SQL Query. This method takes a flat sequence of elements and then organizes the elements into groups (i.e. IGrouping<TKey, TSource>) based on a given key.

How does group by handle Nulls?

We can see that the first result value is a NULL represented by an empty string (the empty line before the IT department). This empty space represents all the NULL values returned by the GROUP BY clause, so we can conclude that GROUP BY treats NULLs as valid values.

What is groupby in SQL?

If two keys are considered equal according to comparer, the first key is chosen as the key for that grouping. In query expression syntax, a group by (Visual C#) or Group By Into (Visual Basic) clause translates to an invocation of GroupBy. For more information and usage examples, see group clause and Group By Clause.


Video Answer


1 Answers

This is probably the shortest solution:

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

Note that the "key" of the groups will be of object type. For null elements I create a new "empty" object. The equality comparer of objects will make so that they are all different. For not-null numbers I simply box them in an object. Boxed integers maintain the equality operator. So:

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

and

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

and

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

a more correct solution would be implementing an 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 :-)
    }
}

and using it:

var grouped2 = MyList.GroupBy(f => f.GroupId, key => new { Object = key }, new MyComparer());
like image 109
xanatos Avatar answered Sep 22 '22 09:09

xanatos