我有一个类项目与属性(Id,名称,代码,价格)。

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

为例:

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

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


当前回答

试试这个扩展方法。希望这能有所帮助。

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);

其他回答

使用Distinct(),但请记住,它使用默认的相等比较器来比较值,因此如果您想要其他的比较器,则需要实现自己的比较器。

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

一个通用的扩展方法:

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());
    }
}

用法示例:

var lstDst = lst.DistinctBy(item => item.Key);
var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First());

当你不想写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; }
}

你有三个选项来删除列表中的重复项:

Use a a custom equality comparer and then use Distinct(new DistinctItemComparer()) as @Christian Hayter mentioned. Use GroupBy, but please note in GroupBy you should Group by all of the columns because if you just group by Id 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 and GetHashCode 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();