【问题标题】:Remove items from one list in another从另一个列表中删除项目
【发布时间】:2011-02-14 06:58:02
【问题描述】:

我试图弄清楚如何遍历我想从另一个项目列表中删除的通用项目列表。

假设我有这个作为假设的例子

List<car> list1 = GetTheList();
List<car> list2 = GetSomeOtherList();

我想用 foreach 遍历 list1 并删除 List1 中也包含在 List2 中的每个项目。

我不太确定该怎么做,因为 foreach 不是基于索引的。

【问题讨论】:

  • 您想删除 List1 中同时也在 List2 中的项目?
  • 如果你有 list1 = { foo1 } 和 list2 = { foo1, foo1 } 会发生什么。应该从 list2 中删除 foo1 的所有副本,还是只删除第一个?
  • -1 - 我对这个问题的每个答案都投了反对票,因为我认为他们都错了,但看起来这个问题只是被问得很糟糕。现在,我无法改变它们——抱歉。您想从list1 中删除list2 中存在的项目,还是要从list2 中删除list1 中存在的项目?在发表此评论时,提供的每个答案都将执行后者。
  • @John Rashch,你应该对那些反对票不那么高兴。一些答案是相当概念性的,仅演示如何实现 OP 想要的,甚至与问题中提到的列表无关。
  • @Mark - 你是对的,完全是我的错 - 这就是为什么我把评论放在这里解释发生了什么,我正在寻找以前的答案,同时我已经遇到过类似的问题在我投票之后,我发现它后打算离开 cmets - 事实证明这不是最好的过程!

标签: c# .net list


【解决方案1】:

你可以使用Except:

List<car> list1 = GetTheList();
List<car> list2 = GetSomeOtherList();
List<car> result = list2.Except(list1).ToList();

你可能甚至不需要那些临时变量:

List<car> result = GetSomeOtherList().Except(GetTheList()).ToList();

请注意,Except 不会修改任何一个列表 - 它会使用结果创建一个新列表。

【讨论】:

  • 次要问题,但这会产生IEnumerable&lt;car&gt;,而不是List&lt;car&gt;。您需要致电ToList() 来获取列表。另外,我认为应该是GetSomeOtherList().Except(GetTheList()).ToList()
  • 如果您之前没有using System.Linq;,您还需要它。
  • 注意:list1.Except(list2) 不会给出与 list2.Except(list1) 相同的结果。最后一个对我有用。
  • 在使用Except 时要小心,因为它实际上执行了一个set 操作,它区分了结果列表。我没有预料到这种行为,因为我使用的是List,而不是HashSetRelated.
  • 为什么这是正确的答案?当然,这可能会在您的上下文中为您提供所需的内容,但是,“从另一个列表中删除项目”当然不等同于设置差异操作,您不应该通过接受这个作为正确答案来误导人们!!!!
【解决方案2】:

您不需要索引,因为List&lt;T&gt; 类允许您按值而不是使用Remove 函数的索引来删除项目。

foreach(car item in list1) list2.Remove(item);

【讨论】:

  • +1,但 IMO 您应该在 list2.Remove(item); 语句周围使用方括号。
  • @sr pt:我总是在出现在另一行的语句上使用括号,但不在我可以/确实与流控制语句放在同一行的单语句块上。
  • 只要你是一致的,你是否使用括号都没关系.. IMO :)
  • @uriz:不管什么是优雅的,这是唯一真正符合问题所说的答案(删除主列表中的项目);另一个答案创建了一个 new 列表,如果该列表是从另一个调用者传入的,该调用者期望它被修改而不是获取替换列表,则这可能是不可取的。
  • @uriz @AdamRobinson 因为我们正在讨论优雅的解决方案...list1.ForEach(c =&gt; list2.Remove(c));
【解决方案3】:

我建议使用LINQ extension methods。你可以用一行代码轻松完成,如下所示:

list2 = list2.Except(list1).ToList();

这当然是假设您从 list2 中删除的 list1 中的对象是同一个实例。

【讨论】:

  • 它也会删除重复项。
【解决方案4】:

在我的例子中,我有两个不同的列表,有一个共同的标识符,有点像外键。 "nzrytmn"引用的第二种解决方案:

var result =  list1.Where(p => !list2.Any(x => x.ID == p.ID && x.property1 == p.property1)).ToList();

是最适合我的情况。 我需要加载一个没有已注册记录的 DropDownList。

谢谢!!!

这是我的代码:

t1 = new T1();
t2 = new T2();

List<T1> list1 = t1.getList();
List<T2> list2 = t2.getList();

ddlT3.DataSource= list2.Where(s => !list1.Any(p => p.Id == s.ID)).ToList();
ddlT3.DataTextField = "AnyThing";
ddlT3.DataValueField = "IdAnyThing";
ddlT3.DataBind();

【讨论】:

  • 你从来没有解释过 DDlT3 是什么
【解决方案5】:

您可以使用 LINQ,但我会使用 RemoveAll 方法。我认为那是更好地表达您的意图的那个。

var integers = new List<int> { 1, 2, 3, 4, 5 };

var remove = new List<int> { 1, 3, 5 };

integers.RemoveAll(i => remove.Contains(i));

【讨论】:

  • 或者更简单的方法组你可以做 - integers.RemoveAll(remove.Contains);
  • 此解决方案是否比 LINQ 除外方法更快?还是使用更少的资源?
【解决方案6】:
list1.RemoveAll(l => list2.Contains(l));

【讨论】:

  • 又名“完全不纯” :-)
  • 这有什么问题。它看起来比使用除外创建另一个列表更好。尤其是当两个列表都很小时。
  • 由于两个列表方法都是O(N),这将导致O(N^2),这可能是大列表的问题。
【解决方案7】:

解决方案 1:您可以这样做:

List<car> result = GetSomeOtherList().Except(GetTheList()).ToList();

但在某些情况下,此解决方案可能不起作用。如果它不起作用,您可以使用我的第二个解决方案。

解决方案 2:

List<car> list1 = GetTheList();
List<car> list2 = GetSomeOtherList();

我们假设 list1 是您的主列表,而 list2 是您的次要列表,并且您想要获取 list1 的项目而没有 list2 的项目。

 var result =  list1.Where(p => !list2.Any(x => x.ID == p.ID && x.property1 == p.property1)).ToList();

【讨论】:

    【解决方案8】:

    由于Except不修改列表,你可以在List&lt;T&gt;上使用ForEach

    list2.ForEach(item => list1.Remove(item));
    

    这可能不是最有效的方法,但它很简单,因此可读,并且会更新原始列表(这是我的要求)。

    【讨论】:

      【解决方案9】:

      来吧..

          List<string> list = new List<string>() { "1", "2", "3" };
          List<string> remove = new List<string>() { "2" };
      
          list.ForEach(s =>
              {
                  if (remove.Contains(s))
                  {
                      list.Remove(s);
                  }
              });
      

      【讨论】:

      • -1。这将在删除第一项后引发异常。此外,(通常)遍历列表以 remove 是一个更好的主意,因为它通常更小。你也强迫更多的列表遍历这样做。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-06
      • 1970-01-01
      • 2015-04-02
      • 1970-01-01
      相关资源
      最近更新 更多