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

时间:2009-10-22 11:48:27

标签: c# linq linq-to-objects generic-list

我有Items的课程properties (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

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

11 个答案:

答案 0 :(得分:538)

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

答案 1 :(得分:346)

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

答案 2 :(得分:34)

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

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

答案 3 :(得分:25)

这就是我能够与Linq分组的方式。希望它有所帮助。

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

答案 4 :(得分:16)

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

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

答案 5 :(得分:12)

此处有三个选项可用于删除列表中的重复项目:

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

答案 6 :(得分:4)

通用扩展方法:

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(g => g.Key);

答案 7 :(得分:3)

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

答案 8 :(得分:3)

尝试使用此扩展方法。希望这可以提供帮助。

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

答案 9 :(得分:0)

另一种解决方法,不是美观的购买方法。

我有一个XML文件,其中包含一个名为“ MEMDES”的元素,其两个属性分别为“ GRADE”和“ SPD”,以记录RAM模块信息。 SPD中有很多易碎的物品。

因此,这是我用于删除成对物品的代码:

        IEnumerable<XElement> MList =
            from RAMList in PREF.Descendants("MEMDES")
            where (string)RAMList.Attribute("GRADE") == "DDR4"
            select RAMList;

        List<string> sellist = new List<string>();

        foreach (var MEMList in MList)
        {
            sellist.Add((string)MEMList.Attribute("SPD").Value);
        }

        foreach (string slist in sellist.Distinct())
        {
            comboBox1.Items.Add(slist);
        }

答案 10 :(得分:-1)

如果您不想编写IEqualityComparer,可以尝试以下内容。

public static void InsertBulk(string procedure, IDictionary<T,T> paramData)
        {

       }

IDictionary<int,string> myparams= new IDictionary<int,string>();