Obtenga una lista distinta basada en una o más propiedades en C#

Bilal Shahid 12 octubre 2023
  1. Use GroupBy() y Select() para obtener una lista distinta basada en una propiedad en C#
  2. Use GroupBy() y Select() para obtener una lista distinta basada en una o más propiedades en C#
  3. Use DistinctBy para obtener una lista distinta basada en una o más propiedades en C#
Obtenga una lista distinta basada en una o más propiedades en C#

Hoy veremos cómo podemos usar Distinct() en LINQ en varios objetos con las mismas propiedades que contienen valores diferentes. Para empezar, eche un vistazo al siguiente ejemplo.

Suponga que tiene tres objetos: AUTO uno, AUTO dos y AUTO tres. CAR one y CAR two contienen valores de construcción de 2, pero CAR three tiene un valor de construcción de 4.

Al llamar a Distinct() en los tres objetos, el resultado solo debe incluir CAR uno y CAR tres o CAR dos y CAR tres, ya que ambos contienen valores distintos.

Este artículo discutirá la obtención de una lista distinta basada en una o más propiedades en C#.

Use GroupBy() y Select() para obtener una lista distinta basada en una propiedad en C#

Entonces, antes de comenzar nuestro ejemplo, primero agreguemos la biblioteca LINQ a nuestro código:

using SYSTEM.Linq;

Entonces avancemos y definamos nuestra clase CAR de la siguiente manera:

class CAR {
  public int id;

  public CAR(int id) {
    this.id = id;
  }
}

Y luego, en el Principal, definamos algunos objetos:

CAR one = new CAR(4);
CAR two = new CAR(4);
CAR three = new CAR(6);

List<CAR> cars = new List<CAR>();
cars.Add(one);
cars.Add(two);
cars.Add(three);

También hemos hecho una lista y le hemos agregado los tres objetos. Recortaremos los mismos objetos de propiedad y solo consideraremos uno de ellos.

Crearemos una nueva lista, luego usaremos la cláusula GroupBY(). Y por último, el Primero() para elegir al ganador.

List<CAR> distinct_c = cars.GroupBy(p => p.id).Select(g => g.First()).ToList();
for (int i = 0; i < distinct_c.Count(); i++) {
  Console.Write(distinct_c[i].id + " ");
}

El resultado saldrá de la siguiente manera:

4 6

Estas fueron las dos identificaciones distintas en cada uno de los tres objetos. Todo el código es el siguiente:

class pointer {
  class CAR {
    public int id;

    public CAR(int id) {
      this.id = id;
    }
  }

  public static void Main(String[] args) {
    CAR one = new CAR(4);
    CAR two = new CAR(4);
    CAR three = new CAR(6);

    List<CAR> cars = new List<CAR>();
    cars.Add(one);
    cars.Add(two);
    cars.Add(three);

    List<CAR> distinct_c = cars.GroupBy(p => p.id).Select(g => g.First()).ToList();
    for (int i = 0; i < distinct_c.Count(); i++) {
      Console.Write(distinct_c[i].id + " ");
    }
  }
}

Inserte el código anterior en su espacio de nombres y luego juegue con él.

Use GroupBy() y Select() para obtener una lista distinta basada en una o más propiedades en C#

¿Qué pasaría si tuviéramos una propiedad más llamada color junto con id y todavía quisiéramos elegir la distinta? Agreguemos la propiedad color a nuestra clase CAR de la siguiente manera:

class CAR {
  public int id;
  public string color;

  public CAR(int id, string color) {
    this.id = id;
    this.color = color;
  }
}

Sin embargo, si tuviera que llamar ahora a la función con la misma sintaxis que la anterior:

CAR one = new CAR(4, "red");
CAR two = new CAR(4, "blue");
CAR three = new CAR(6, "blue");

List<CAR> cars = new List<CAR>();
cars.Add(one);
cars.Add(two);
cars.Add(three);

List<CAR> distinct_c = cars.GroupBy(p => p.id).Select(g => g.First()).ToList();
for (int i = 0; i < distinct_c.Count(); i++) {
  Console.Write(distinct_c[i].id + " ");
}

La salida permanecería igual que 4 6. Porque p todavía se agrupa solo por p => p.id. Pero ahora que también queremos distinguir por color, podemos hacer algo de la siguiente manera:

List<CAR> distinct_c = cars.GroupBy(p => (p.id, p.color)).Select(g => g.First()).ToList();
for (int i = 0; i < distinct_c.Count(); i++) {
  Console.Write(distinct_c[i].id + " ");
}

Entonces, ¿cuál será el resultado? Porque los tres objetos tienen todas las diferentes combinaciones de ID y CAR como; (4, rojo), (4, azul) y (6, azul). Por lo tanto, hay una distinción entre todos los objetos.

La salida ahora será:

4 4 6

El código completo se proporciona a continuación:

using System;
using System.Collections.Generic;
using System.Linq;

static class pointer {
  class CAR {
    public int id;
    public string color;

    public CAR(int id, string color) {
      this.id = id;
      this.color = color;
    }
  }

  public static void Main(String[] args) {
    CAR one = new CAR(4, "red");
    CAR two = new CAR(4, "blue");
    CAR three = new CAR(6, "blue");

    List<CAR> cars = new List<CAR>();
    cars.Add(one);
    cars.Add(two);
    cars.Add(three);

    List<CAR> distinct_c = cars.GroupBy(p => (p.id, p.color)).Select(g => g.First()).ToList();
    for (int i = 0; i < distinct_c.Count(); i++) {
      Console.Write(distinct_c[i].id + " ");
    }
  }
}

Incluso puede agregar una condición Dónde para verificar si el p.id no es nulo y luego llamarlo:

List<CAR> distinct_c =
    cars.Where(p => p.id != null).GroupBy(p => (p.id, p.color)).Select(g => g.First()).ToList();
for (int i = 0; i < distinct_c.Count(); i++) {
  Console.Write(distinct_c[i].id + " ");
}

El resultado también será el mismo.

Puntos a considerar al usar First() en C#

A veces, puedes salirte con la tuya con FirstorDefault(). Otra función que hace lo mismo que First(), pero si no hay un primer elemento, solo devolverá un valor predeterminado.

Se puede utilizar para evitar errores en valores nulos.

Use DistinctBy para obtener una lista distinta basada en una o más propiedades en C#

Puede escribir una función que pueda devolver valores distintos en C#.

Una forma de hacerlo puede ser usar tablas hash que puedan tomar una clave y un valor y mapearlos juntos. Puedes escribir una función como esa de la siguiente manera:

public static IEnumerable<S> DistinctBy<S, K>(this IEnumerable<S> source, Func<S, K> keySelector) {
  HashSet<K> seen = new HashSet<K>();
  foreach (S element in source) {
    if (seen.Add(keySelector(element))) {
      yield return element;
    }
  }
}

Sin embargo, antes de esto, asegúrese de descargar MORELINQ y configurarlo para su código.

var q = cars.DistinctBy(p => p.id);

Y luego, puede imprimir el contenido de esta variable q y obtener la respuesta. El código completo se muestra a continuación:

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using MoreLinq;

namespace jinlku_console {
  static class pointer {
    class CAR {
      public int id;
      public string color;

      public CAR(int id, string color) {
        this.id = id;
        this.color = color;
      }
    }

    public static IEnumerable<S> DistinctBy<S, K>(this IEnumerable<S> source,
                                                  Func<S, K> keySelector) {
      HashSet<K> seen = new HashSet<K>();
      foreach (S element in source) {
        if (seen.Add(keySelector(element))) {
          yield return element;
        }
      }
    }

    public static void Main(String[] args) {
      CAR one = new CAR(4, "red");
      CAR two = new CAR(4, "blue");
      CAR three = new CAR(6, "blue");

      List<CAR> cars = new List<CAR>();
      cars.Add(one);
      cars.Add(two);
      cars.Add(three);

      var q = cars.DistinctBy(p => p.id);

      Console.WriteLine(q.Count());

      List<CAR> distinct_c = cars.GroupBy(p => (p.id, p.color)).Select(g => g.First()).ToList();
      for (int i = 0; i < distinct_c.Count(); i++) {
        Console.Write(distinct_c[i].id + " ");
      }
    }
  }
}

Otra Solución Sencilla para Obtener una Lista Distinta Basada en una o Más Propiedades en C#

Otra forma de escribir la misma consulta puede ser la siguiente:

var un = from car in cars group car by new(car.id) into mg select mg.First();

Sin embargo, para usar esto, es posible que deba actualizar su idioma a 9.0 o superior.

Bilal Shahid avatar Bilal Shahid avatar

Hello, I am Bilal, a research enthusiast who tends to break and make code from scratch. I dwell deep into the latest issues faced by the developer community and provide answers and different solutions. Apart from that, I am just another normal developer with a laptop, a mug of coffee, some biscuits and a thick spectacle!

GitHub

Artículo relacionado - Csharp LINQ