C# 使用 linq 删除列表中的重复项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1606679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Remove duplicates in the list using linq
提问by Prasad
I have a class Items
with properties (Id, Name, Code, Price)
.
我有一个类Items
有properties (Id, Name, Code, Price)
。
The List of Items
is populated with duplicated items.
List ofItems
填充了重复的项目。
For ex.:
例如:
1 Item1 IT00001 0
2 Item2 IT00002 0
3 Item3 IT00003 0
1 Item1 IT00001 0
3 Item3 IT00003 0
How to remove the duplicates in the list using linq?
如何使用 linq 删除列表中的重复项?
采纳答案by Christian Hayter
var distinctItems = items.Distinct();
To match on only some of the properties, create a custom equality comparer, e.g.:
要仅匹配某些属性,请创建自定义相等比较器,例如:
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();
}
}
Then use it like this:
然后像这样使用它:
var distinctItems = items.Distinct(new DistinctItemComparer());
回答by Brian Rasmussen
Use Distinct()
but keep in mind that it uses the default equality comparer to compare values, so if you want anything beyond that you need to implement your own comparer.
使用Distinct()
但请记住,它使用默认的相等比较器来比较值,因此如果您想要除此之外的任何内容,则需要实现自己的比较器。
Please see http://msdn.microsoft.com/en-us/library/bb348436.aspxfor an example.
有关示例,请参阅http://msdn.microsoft.com/en-us/library/bb348436.aspx。
回答by tvanfosson
回答by Freddy
var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First());
回答by Victor Juri
This is how I was able to group by with Linq. Hope it helps.
这就是我能够与 Linq 分组的方式。希望能帮助到你。
var query = collection.GroupBy(x => x.title).Select(y => y.FirstOrDefault());
回答by Arun Kumar
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();
回答by Salah Akbari
You have three option here for removing duplicate item in your List:
您在此处有三个选项可用于删除列表中的重复项:
- Use a a custom equality comparer and then use
Distinct(new DistinctItemComparer())
as @Christian Haytermentioned. Use
GroupBy
, but please note inGroupBy
you should Group by all of the columns because if you just group byId
it doesn't remove duplicate items always. For example consider the following example: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());
The result for this grouping will be:
{Id = 1, Name = "Item1", Code = "IT00001", Price = 100} {Id = 2, Name = "Item2", Code = "IT00002", Price = 200} {Id = 3, Name = "Item3", Code = "IT00003", Price = 150}
Which is incorrect because it considers
{Id = 3, Name = "Item3", Code = "IT00004", Price = 250}
as duplicate. So the correct query would be:var distinctItems = a.GroupBy(c => new { c.Id , c.Name , c.Code , c.Price}) .Select(c => c.First()).ToList();
3.Override
Equal
andGetHashCode
in item class: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(); } }
Then you can use it like this:
var distinctItems = a.Distinct();
- 使用AA自定义相等比较,然后使用
Distinct(new DistinctItemComparer())
作为@Christian艾泰提及。 使用
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.Override
Equal
andGetHashCode
in item类: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();
回答by Kent Aguilar
Try this extension method out. Hopefully this could help.
试试这个扩展方法。希望这会有所帮助。
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)));
}
}
Usage:
用法:
var outputList = sourceList.DistinctBy(x => x.TargetProperty);
回答by Kundan Bhati
When you don't want to write IEqualityComparer you can try something like following.
当您不想编写 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; }
}
回答by TOL
An universal extension method:
通用扩展方法:
public static class EnumerableExtensions
{
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> enumerable, Func<T, TKey> keySelector)
{
return enumerable.GroupBy(keySelector).Select(grp => grp.First());
}
}
Example of usage:
用法示例:
var lstDst = lst.DistinctBy(item => item.Key);