使用linq删除列表中的重复项

我有一个类properties (Id, Name, Code, Price) Items properties (Id, Name, Code, Price)

项目列表中填充了重复的项目。

例如:

 1 Item1 IT00001 $100 2 Item2 IT00002 $200 3 Item3 IT00003 $150 1 Item1 IT00001 $100 3 Item3 IT00003 $150 

如何使用linq删除列表中的重复项?

 var distinctItems = items.Distinct(); 

要仅匹配某些属性,请创建一个自定义的相等比较器,例如:

 class DistinctItemComparer : IEqualityComparer<Item> { public bool Equals(Item x, Item y) { return x.Id == y.Id && x.Name == y.Name && x.Code == y.Code && x.Price == y.Price; } public int GetHashCode(Item obj) { return obj.Id.GetHashCode() ^ obj.Name.GetHashCode() ^ obj.Code.GetHashCode() ^ obj.Price.GetHashCode(); } } 

然后像这样使用它:

 var distinctItems = items.Distinct(new DistinctItemComparer()); 
 var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First()); 

如果有什么东西抛出你的区别查询,你可能想看看MoreLinq并使用DistinctBy运算符并通过id选择不同的对象。

 var distinct = items.DistinctBy( i => i.Id ); 

这就是我能和Linq一起分组的原因。 希望它有帮助。

 var query = collection.GroupBy(x => x.title).Select(y => y.FirstOrDefault()); 

使用Distinct()但请记住,它使用默认的相等比较器来比较值,所以如果你想要的东西以外,你需要实现自己的比较器。

有关示例,请参阅http://msdn.microsoft.com/en-us/library/bb348436.aspx

您有三个选项可以删除列表中的重复项目:

  1. 使用自定义相等比较器,然后使用Distinct(new DistinctItemComparer())作为@Christian Hayter提到。
  2. 使用GroupBy ,但请注意在GroupBy你应该分组所有的列,因为如果你只是按Id分组它不会总是删除重复的项目。 例如考虑下面的例子:

     List<Item> a = new List<Item> { new Item {Id = 1, Name = "Item1", Code = "IT00001", Price = 100}, new Item {Id = 2, Name = "Item2", Code = "IT00002", Price = 200}, new Item {Id = 3, Name = "Item3", Code = "IT00003", Price = 150}, new Item {Id = 1, Name = "Item1", Code = "IT00001", Price = 100}, new Item {Id = 3, Name = "Item3", Code = "IT00003", Price = 150}, new Item {Id = 3, Name = "Item3", Code = "IT00004", Price = 250} }; var distinctItems = a.GroupBy(x => x.Id).Select(y => y.First()); 

    这个分组的结果是:

     {Id = 1, Name = "Item1", Code = "IT00001", Price = 100} {Id = 2, Name = "Item2", Code = "IT00002", Price = 200} {Id = 3, Name = "Item3", Code = "IT00003", Price = 150} 

    这是不正确的,因为它认为{Id = 3, Name = "Item3", Code = "IT00004", Price = 250}重复。 所以正确的查询将是:

     var distinctItems = a.GroupBy(c => new { c.Id , c.Name , c.Code , c.Price}) .Select(c => c.First()).ToList(); 

    3.在项目类中覆盖EqualGetHashCode

     public class Item { public int Id { get; set; } public string Name { get; set; } public string Code { get; set; } public int Price { get; set; } public override bool Equals(object obj) { if (!(obj is Item)) return false; Item p = (Item)obj; return (p.Id == Id && p.Name == Name && p.Code == Code && p.Price == Price); } public override int GetHashCode() { return String.Format("{0}|{1}|{2}|{3}", Id, Name, Code, Price).GetHashCode(); } } 

    那么你可以像这样使用它:

     var distinctItems = a.Distinct(); 
 List<Employee> employees = new List<Employee>() { new Employee{Id =1,Name="AAAAA"} , new Employee{Id =2,Name="BBBBB"} , new Employee{Id =3,Name="AAAAA"} , new Employee{Id =4,Name="CCCCC"} , new Employee{Id =5,Name="AAAAA"} }; List<Employee> duplicateEmployees = employees.Except(employees.GroupBy(i => i.Name) .Select(ss => ss.FirstOrDefault())) .ToList(); 

试试这个扩展方法。 希望这可以帮助。

 public static class DistinctHelper { public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { var identifiedKeys = new HashSet<TKey>(); return source.Where(element => identifiedKeys.Add(keySelector(element))); } } 

用法:

 var outputList = sourceList.DistinctBy(x => x.TargetProperty); 

当你不想写IEqualityComparer时,你可以尝试像下面这样的东西。

  class Program { private static void Main(string[] args) { var items = new List<Item>(); items.Add(new Item {Id = 1, Name = "Item1"}); items.Add(new Item {Id = 2, Name = "Item2"}); items.Add(new Item {Id = 3, Name = "Item3"}); //Duplicate item items.Add(new Item {Id = 4, Name = "Item4"}); //Duplicate item items.Add(new Item {Id = 2, Name = "Item2"}); items.Add(new Item {Id = 3, Name = "Item3"}); var res = items.Select(i => new {i.Id, i.Name}) .Distinct().Select(x => new Item {Id = x.Id, Name = x.Name}).ToList(); // now res contains distinct records } } public class Item { public int Id { get; set; } public string Name { get; set; } }