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

Pra*_*sad 282 c# linq linq-to-objects generic-list

我上课Itemsproperties (Id, Name, Code, Price).

列表中Items填充了重复的项目.

例如:

1         Item1       IT00001        $100
2         Item2       IT00002        $200
3         Item3       IT00003        $150
1         Item1       IT00001        $100
3         Item3       IT00003        $150
Run Code Online (Sandbox Code Playgroud)

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

小智 563

var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First());
Run Code Online (Sandbox Code Playgroud)

  • 谢谢 - 希望避免编写比较类,所以我很高兴这很有效:) (27认同)
  • +1此解决方案甚至允许打破平局:消除重复标准! (8认同)
  • 但是有点开销! (4认同)
  • 您可以使用多个属性进行分组:List <XYZ> MyUniqueList = MyList.GroupBy(x => new {x.Column1,x.Column2}).选择(g => g.First()).ToList(); (4认同)
  • 但是,正如 Victor Juri 下面建议的那样:使用 FirstorDefault。不敢相信,这个解决方案可以如此简单(没有自定义相等比较器) (2认同)

Chr*_*ter 363

var distinctItems = items.Distinct();
Run Code Online (Sandbox Code Playgroud)

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

var distinctItems = items.Distinct(new DistinctItemComparer());
Run Code Online (Sandbox Code Playgroud)

  • 我发现比较器类非常有用。除了简单的属性名称比较之外,它们还可以表达逻辑。上个月,我写了一篇新书,做了“ GroupBy”无法做的事情。 (2认同)

tva*_*son 37

如果有什么东西会抛弃您的Distinct查询,您可能需要查看MoreLinq并使用DistinctBy运算符并按ID选择不同的对象.

var distinct = items.DistinctBy( i => i.Id );
Run Code Online (Sandbox Code Playgroud)

  • @FereydoonBarikzehy但他并不是在谈论纯粹的Linq.在帖子中是linq到MoreLinq项目...... (7认同)
  • 在 .NET 6+ 中现在有 DistinctBy() (2认同)

小智 29

这就是我能够与Linq分组的方式.希望能帮助到你.

var query = collection.GroupBy(x => x.title).Select(y => y.FirstOrDefault());
Run Code Online (Sandbox Code Playgroud)

  • 如果我是正确的,那么使用`FirstOrDefault`这里没有任何好处,如果`Select`紧跟在'GroupBy'之后,因为没有可能存在空组(这些组是_just derived_来自集合的内容) (19认同)
  • @nawfal,我建议使用FirstOrDefault()代替First() (3认同)

Bri*_*sen 17

使用Distinct(),但请记住,它使用默认的相等比较器对值进行比较,所以如果你想超出了任何你需要实现自己的比较器.

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


Sal*_*ari 13

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

  1. 使用AA自定义相等比较,然后使用Distinct(new DistinctItemComparer())作为@Christian艾泰提及.
  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());
    
    Run Code Online (Sandbox Code Playgroud)

    此分组的结果将是:

    {Id = 1, Name = "Item1", Code = "IT00001", Price = 100}
    {Id = 2, Name = "Item2", Code = "IT00002", Price = 200}
    {Id = 3, Name = "Item3", Code = "IT00003", Price = 150}
    
    Run Code Online (Sandbox Code Playgroud)

    哪个不正确,因为它认为{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();
    
    Run Code Online (Sandbox Code Playgroud)

    3.Override 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();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    然后你可以像这样使用它:

    var distinctItems = a.Distinct();
    
    Run Code Online (Sandbox Code Playgroud)


TOL*_*TOL 10

通用扩展方法:

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

var lstDst = lst.DistinctBy(item => item.Key);
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这正是我正在寻找的,效果很好。 (2认同)

Ken*_*lar 5

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

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)));
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

var outputList = sourceList.DistinctBy(x => x.TargetProperty);
Run Code Online (Sandbox Code Playgroud)