c# - multiple - Linq GroupBy con cada valor nulo como grupo
linq group by count (2)
Tengo un objeto con una propiedad int nullable "GroupId".
Con una Lista de este objeto, me gustaría hacer un GroupBy en este "GroupId". Pero si lo hago, todos los valores nulos formarán un grupo.
Ejemplo:
Objeto 1: ID de grupo: NULO
Objeto 2: ID de grupo: NULO
Objeto 3: ID de grupo: 1
Objeto 4: ID de grupo: 1
Objeto 5: ID de grupo: 2
Objeto 6: ID de grupo: 2
MyList.GroupBy(f => f.GroupId, key => new {Object = key});
Conseguiré 3 grupos.
¿Cómo puedo obtener 4 grupos en su lugar? Un grupo por cada valor NULL ...
Esta es probablemente la solución más corta:
var grouped = MyList.GroupBy(f => f.GroupId != null ? (object)f.GroupId : new object(), key => new { Object = key });
Tenga en cuenta que la "clave" de los grupos será del tipo de object
. Para elementos null
, creo un nuevo object
"vacío". El comparador de igualdad de objetos hará que todos sean diferentes. Para números no nulos, simplemente los recuadro en un objeto. Los enteros en caja mantienen el operador de igualdad. Asi que:
new object().Equals(new object()) == false // always
y
((object)1).Equals((object)1) == true // always
y
((object)1).Equals((object)2) == false // always
una solución más correcta sería implementar un 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 :-)
}
}
y usándolo:
var grouped2 = MyList.GroupBy(f => f.GroupId, key => new { Object = key }, new MyComparer());
Comparer genérico que se puede utilizar sin boxeo.
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();
}
}
Entonces lo usarías como:
// where GroupId as a nullable Guid
var grouped = MyList.GroupBy(f => f.GroupId, new NullableComparer<Guid>());