class obj
{
int typeId; //10 types 0-9
string uniqueString; //this is unique
}
Suponga que hay una lista con 100 elementos de obj, pero solo 10 typeID únicos.
¿Es posible escribir una consulta LINQ que devuelva las 10 entradas únicas de la lista de objs?
Respuestas:
fuente
Suponiendo que desea el objeto completo, pero solo desea lidiar con la distinción
typeID
, no hay nada integrado en LINQ para facilitar esto. (Si solo desea lostypeID
valores, es fácil: proyecte a esoSelect
y luego use laDistinct
llamada normal ).En MoreLINQ tenemos el
DistinctBy
operador que puede utilizar:var distinct = list.DistinctBy(x => x.typeID);
Sin embargo, esto solo funciona para LINQ to Objects.
Puede usar una agrupación o una búsqueda, es algo molesto e ineficiente:
var distinct = list.GroupBy(x => x.typeID, (key, group) => group.First());
fuente
Si solo desea usar Linq puro, puede usar groupby:
Si desea que se utilice un método en toda la aplicación, similar a lo que hace MoreLinq :
public static IEnumerable<TSource> DistinctBy<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { HashSet<TKey> seenKeys = new HashSet<TKey>(); foreach (TSource element in source) { if (!seenKeys.Contains(keySelector(element))) { seenKeys.Add(keySelector(element)); yield return element; } } }
Usando este método para encontrar los valores distintos usando solo la propiedad Id, puede usar:
var query = objs.DistinctBy(p => p.TypeId);
puede utilizar varias propiedades:
var query = objs.DistinctBy(p => new { p.TypeId, p.Name });
fuente
Claro, usa
Enumerable.Distinct
.Dada una colección de
obj
(por ejemplofoo
), harías algo como esto:var distinctTypeIDs = foo.Select(x => x.typeID).Distinct();
fuente
Creo que esto es lo que estás buscando:
var objs= (from c in List_Objects orderby c.TypeID select c).GroupBy(g=>g.TypeID).Select(x=>x.FirstOrDefault());
Similar a esto ¿ Devolver un IQueryable distinto con LINQ?
fuente
.First
está bien, ya que no tendrías el grupo si no hubiera algo en él.GroupBy
para simplificar esto también; vea mi respuesta para ver un ejemplo.Si solo desea usar Linq, puede anular los métodos Equals y GetHashCode .
Clase de producto :
public class Product { public string ProductName { get; set; } public int Id { get; set; } public override bool Equals(object obj) { if (!(obj is Product)) { return false; } var other = (Product)obj; return Id == other.Id; } public override int GetHashCode() { return Id.GetHashCode(); } }
Método principal :
static void Main(string[] args) { var products = new List<Product> { new Product{ ProductName="Product 1",Id = 1}, new Product{ ProductName="Product 2",Id = 2}, new Product{ ProductName="Product 4",Id = 5}, new Product{ ProductName="Product 3",Id = 3}, new Product{ ProductName="Product 4",Id = 4}, new Product{ ProductName="Product 6",Id = 4}, new Product{ ProductName="Product 6",Id = 4}, }; var itemsDistinctByProductName = products.Distinct().ToList(); foreach (var product in itemsDistinctByProductName) { Console.WriteLine($"Product Id : {product.Id} ProductName : {product.ProductName} "); } Console.ReadKey(); }
fuente
Quería vincular un dato particular al menú desplegable y debería ser distinto. Hice lo siguiente:
List<ClassDetails> classDetails; List<string> classDetailsData = classDetails.Select(dt => dt.Data).Distinct.ToList(); ddlData.DataSource = classDetailsData; ddlData.Databind();
Mira si ayuda
fuente