【问题标题】:Remove Duplicate item from list based on condition根据条件从列表中删除重复项
【发布时间】:2012-05-21 21:26:23
【问题描述】:

我有一个具有属性(名称、价格)的类 Items。

   Item1       $100
   Item2       $200
   Item3       $150
   Item1       $500
   Item3       $150

仅当名称存在多次且价格为 500 美元(使用 LINQ 且不创建自定义比较器)时,我才想删除项目?对于上述 500 美元的项目 1,将从列表中删除。

谢谢,

【问题讨论】:

    标签: c# linq c#-4.0


    【解决方案1】:

    试试这个:

    var result = items
        .GroupBy(item => item.Name)
        .SelectMany(g => g.Count() > 1 ? g.Where(x => x.Price != 500) : g);
    

    按名称排列的第一组。如果该组的商品多于 1 件,请仅从该组中选择价格不为 500 的商品。

    【讨论】:

    • 这将删除价格为 500 的商品,即使它不是重复的。
    • 为这些好东西加一分。
    【解决方案2】:
    var result =
        from item in items
        where item.Price != 500 || items.Count(i => i.Name == item.Name) == 1
        select item;
    

    【讨论】:

      【解决方案3】:

      我将首先创建一个包含重复项的预评估子集列表:

      var dupes = list.Where(a => list.Count(b => b.Name.Equals(a.Name)) > 1).ToList();
      

      .ToList() 确保此查询只评估一次。如果列表很大,这将在速度上产生巨大差异。

      现在如果您的列表是List<>,您可以使用RemoveAll() 方法:

      list.RemoveAll(item => item.Price == 500 && dupes.Contains(item));
      

      你已经完成了。

      但是如果你的列表只知道IEnumerable<>,或者你不想修改源列表,或者你想要延迟执行,那么就使用LINQ吧:

      var result = list.Where(item => !(item.Price == 500 && dupes.Contains(item)));
      

      这将在您枚举 result 时进行评估。

      【讨论】:

        【解决方案4】:

        可以通过以下方式查找重复项:

        var dups = lst.Where(x=>lst.Any(y => y != x && y.Name == x.Name))
        

        可以通过以下方式查找价格为500 的重复项目:

        var dups500 = dups.Where(x=>x.Price == 500);
        

        最后可以使用 except 方法来移除 dups500:

        var result = lst.Except(dup);
        

        或多合一:

        var result = 
             lst.Except(
                       lst
                       .Where(x=>x.Price == 500 && 
                                 lst.Any(y => y != x && y.Name == x.Name))).ToList();
        

        【讨论】:

        • @KirkWoll,这取决于你的口味,但这并不令人困惑:Except 表示Except,而内部where 搜索具有给定条件的项目,看起来很简单:) 但这取决于你的选择。 (这也比 groupby one 快)。
        • 这不会同时保留 Item3s
        • @MartinNeal,我听不懂你的意思?
        • @Saeed: Except 返回两个序列的“设置差异”(即,它不包括重复项)。由于在 OP 的示例中有两个项目 {Name="Item3",Price=$150} 那么这些项目之一可能会被 Except 排除(例如,如果它们是同一个对象;或者如果它们有一个 Equals 方法将它们视为平等;或者如果您使用IEqualityComparer<> 将它们视为平等)。但是,如果它们不被认为是相等的并且它们只是碰巧具有相同名称和价格的两个对象,那么您就可以了。
        • 嗯,这取决于 OP 对他的 Item 类有什么。我正在使用匿名类进行测试,而 y!=x 部分的行为有所不同。
        【解决方案5】:
        var result = from np in NamePriceCollection
        where NamePriceCollection.Count(x => x.Name == np.Name) > 1 && np.Price == 500
        select np;
        

        // 你在这里有指定条件的项目列表。从基础集合中删除它们

        【讨论】:

          【解决方案6】:

          仅当名称存在多次且价格为 500 美元时,我才想删除项目

          Apple 300 <-- winner
          Apple 500 <-- dupe
          Banana 500  <-- winner
          Banana 500  <-- dupe
          Banana 500  <-- dupe
          Cantelope 100 <-- winner
          Cantelope 200 <-- winner
          

          显然,第二个苹果是骗子。 Banana 有三件商品,价格 == 500。一件是赢家。其余的都是骗子。没有价格 == 500 Cantelopes,所以没有骗子,只有赢家。

          from item in source
          group item by item.Name into g
          let okItems = g.Where(x => x.Price != 500)
          let secondChoiceItem = g.FirstOrDefault(x => x.Price == 500)
          let theItems = okItems.DefaultIfEmpty(secondChoiceItem)
          from nonDupeItem in theItems
          select nonDupeItem
          

          【讨论】:

            【解决方案7】:
            var Test = (from row in DataTable.AsEnumerable()
                        select row.Field<string>("ColumnName")).Distinct();
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-08-26
              • 1970-01-01
              • 2011-03-17
              • 2021-03-20
              • 1970-01-01
              • 2019-03-24
              相关资源
              最近更新 更多