Seleccionar distinto usando linq [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Tengo una lista de clases de clase

public class LinqTest
{
public int id { get; set; }
public string value { get; set; }
}


List<LinqTest> myList = new List<LinqTest>();
myList.Add(new LinqTest() { id = 1, value = "a" });
myList.Add(new LinqTest() { id = 1, value = "b" });
myList.Add(new LinqTest() { id = 2, value = "c" });

Necesito seleccionar solo los distintos id de esa lista. es decir, mi lista resultante solo debe contener

[{id=1,value="a"},{ id = 2, value = "c" }]

¿Cómo puedo hacer esto con linq?

Editar

Entrada,

id      value
1        a
1        b
2        c
3        d
3        e

Fuera put debe ser,

id      value
1        a
2        c
3        d

Es decir, si hay una repetición de id, el resultado debe tomar la primera ocurrencia solamente.

Author: Cœur, 2013-10-16

4 answers

myList.GroupBy(test => test.id)
      .Select(grp => grp.First());

Editar: como obtener esto IEnumerable<> en un List<> parece ser un misterio para muchas personas, simplemente puede escribir:

var result = myList.GroupBy(test => test.id)
                   .Select(grp => grp.First())
                   .ToList();

Pero a menudo es mejor trabajar con IEnumerable en lugar de IList ya que el Linq anterior se evalúa perezosamente: en realidad no hace todo el trabajo hasta que se itera el enumerable. Cuando se llama ToList en realidad camina todo el enumerable forzando todo el trabajo a realizarse por adelantado. (Y puede tomar un poco de tiempo si su enumerable es infinitamente largo.)

La otra cara de este consejo es que cada vez que enumere tal IEnumerable el trabajo para evaluarlo tiene que hacerse de nuevo. Por lo tanto, debe decidir para cada caso si es mejor trabajar con el perezosamente evaluado IEnumerable o realizarlo en un List, Set, Dictionary o lo que sea.

 426
Author: Paul Ruane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-04 23:08:03

Usando morelinq puedes usar DistinctBy:

myList.DistinctBy(x => x.id);

De lo contrario, puede usar un grupo:

myList.GroupBy(x => x.id)
      .Select(g => g.First());
 97
Author: Daniel Hilgarth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-18 15:28:41

Debe anular Equals y GetHashCode de manera significativa, en este caso para comparar el ID:

public class LinqTest
{
    public int id { get; set; }
    public string value { get; set; }

    public override bool Equals(object obj)
    {
        LinqTest obj2 = obj as LinqTest;
        if (obj2 == null) return false;
        return id == obj2.id;
    }

    public override int GetHashCode()
    {
        return id;
    }
}

Ahora puedes usar Distinct:

List<LinqTest> uniqueIDs = myList.Distinct().ToList();
 49
Author: Tim Schmelter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-16 14:40:35
myList.GroupBy(i => i.id).Select(group => group.First())
 23
Author: Tim Rogers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-16 14:36:43