【问题标题】:Remove all occurrences of an item in ArrayList删除 ArrayList 中所有出现的项目
【发布时间】:2014-11-17 10:43:06
【问题描述】:

我正在尝试删除数组列表中所有出现的项目

ArrayList list=new ArrayList();
list.Add("2.2");
list.Add("2.5");
list.Add("2.6");
list.Add("2.2");
list.Add("2.5");
list.Add("2.2");

如何从列表中删除所有2.2值?我用过

list.Remove("2.2")

但它只删除第一次出现

【问题讨论】:

  • 我认为你有一个错字。这是list.Remove 而不是list.remove

标签: c# arraylist


【解决方案1】:

阅读ArrayList.Remove() 上的文档,尤其是:

从 ArrayList 中删除特定对象的第一个匹配项。

你为什么还要使用ArrayList?您示例中的元素都是相同类型的,您最好使用List<string>,然后使用RemoveAll,例如

List<string> list = new List<string>();
list.add("2.2");
list.add("2.5");
list.add("2.6");
list.add("2.2");
list.add("2.5");
list.add("2.2");

list.RemoveAll(item => item == "2.2");

【讨论】:

  • 你为什么要回答 TS 没有问的问题?
  • @ValentinP。当有更好的解决方案可用时,您为什么提供它?当您的元素都是相同类型时使用ArrayList 是完全没有必要的。
  • 我的意思是问题是关于 ArrayList,而不是 List。因此,在这种特定情况下,使用 ArrayList 可能是有意义的。如果你在讨论关于 ArrayList 的问题时谈论 List,我认为首先你应该为 ArrayList 提供解决方案,然后才讲述有关 List 的内容以及为什么它更好。至于我,我认为已经发布了更好的解决方案。
  • using of ArrayList makes sense in this certain case. - 除了它显然不是,因为所有的数组元素都是相同的类型。 ArrayList 已被弃用,属于 C# 没有泛型的时代。使用List&lt;T&gt;,您可以避免转换问题,获得 LINQ 的好处,避免装箱/拆箱值类型,更不用说 ArrayList 消耗 2x as much memory as List&lt;T&gt; on 64 bit machines 的事实,请解释为什么 OP 应该正在使用ArrayList
  • @ValentinP。 OP 有没有理由相信这是一个不完整的代码示例?按照你的逻辑,我们应该如何回答任何问题?毕竟,这可能不是他正确使用的实际代码!有缺陷的推理我的朋友 :) 不客气,坚持下去,你可能会学到一些东西..
【解决方案2】:

ArrayList.Remove的描述很清楚:

从 ArrayList 中删除 特定对象的第一次出现(强调我的)

你可以这样做:

while (list.Contains("2.2"))
{
    list.Remove("2.2");
}

【讨论】:

    【解决方案3】:

    如上所述,使用列表是最佳选择。但如果你坚持使用ArrayList,那么你可以这样做。

    ArrayList list = new ArrayList();
    list.Add("2.2");
    list.Add("2.2");
    list.Add("2.5");
    list.Add("2.6");
    list.Add("2.2");
    list.Add("2.5");
    
    do{
        list.Remove("2.2"); 
    } while (list.Contains("2.2"));
    

    可能是另一种方式..

    list.Sort();
    int i = list.LastIndexOf("2.2");
    int j = list.IndexOf("2.2");
    list.RemoveRange(j,i-j+1);
    

    【讨论】:

      【解决方案4】:

      新方法

      Generic Collections in the .NET Framework 是用来代替过时的ArrayList 的东西,它有一定的设计和性能问题。

      以下是使用List&lt;T&gt; classList&lt;T&gt;.RemoveAll(Predicate) 方法的示例:

      var list=new List<string>();
      list.Add("2.2");
      list.Add("2.5");
      list.Add("2.2");
      // ...
      
      list.RemoveAll(item => item == "2.2");
      

      遗留代码问题

      但是,在某些情况下,我们必须使用过时的 ArrayList 类,例如在使用遗留代码时。

      甚至,有时旧版 API 需要使用相同的 ArrayList 实例,在这种情况下,我们需要一种快速可靠的方法来使用。

      填补空白

      这是一个填补空白的 RemoveAll 扩展的实现:

      public static class ArrayListExtensions
      {
          /// <summary>
          /// Removes all the elements equal to <paramref name="sample"/>.
          /// </summary>
          /// <param name="list">List to remove from.</param>
          /// <param name="sample">Element to remove.</param>
          /// <returns>Returns the number of removed elements.</returns>
          public static int RemoveAll(this ArrayList list, object sample)
          {
              if (list == null)
                  throw new ArgumentNullException("list");
      
              var n = list.Count;
              var nextOut = 0;
              var nextIn = 0;
      
              for (; nextIn < n && nextIn == nextOut; nextIn++)
              {
                  var token = list[nextIn];
                  if (!Equals(token, sample))
                  {
                      nextOut++;
                  }
              }
      
              for (; nextIn < n; nextIn++)
              {
                  var token = list[nextIn];
                  if (!Equals(token, sample))
                  {
                      list[nextOut] = token;
                      nextOut ++;
                  }
              }
      
              if (nextOut < list.Count)
              {
                  var toRemove = list.Count - nextOut;
                  list.RemoveRange(nextOut, toRemove);
                  return toRemove;
              }
      
              return 0;
          }
      }
      

      此方法只进行必要的底层ArrayList API 调用,就地工作,并且除了实际需要的 O(n) 之外没有增加复杂性。

      【讨论】:

      • +1 用于推荐真正的解决方案。绝对没有理由在这里使用ArrayList
      【解决方案5】:

      有很多方法:

      int index;
      while ((index = list.IndexOf("2.2")) > -1)
      {
          list.RemoveAt(index);
      }
      

      或:

      while (list.Contains("2.2"))
      {
          list.Remove("2.2");
      }
      

      或:

      list = new ArrayList(list.Cast<string>().Where(item => s != "2.2"));
      

      【讨论】:

      • 几乎所有这些都非常昂贵,而不必如此。对于长列表..它们肯定会显示这些操作执行得有多差..要小心。
      • @VikasGupta 我同意,但我希望 OP 意识到这一点,因为他正在使用该结构。
      • 这里绝对不需要将算法复杂度提高到 O(N^2)。
      【解决方案6】:

      最简单的方法是使用 lambda 函数和 RemoveAll:

      list.RemoveAll(x => x == 2.2)
      

      【讨论】:

        【解决方案7】:
        ArrayList arryList2 = new ArrayList();
        arryList2.Add(100);
        arryList2.Add(200);
        arryList2.Add(100);
        
        while (arryList2.Contains(100))
        arryList2.Remove(100);
        

        【讨论】:

        • 回答问题很好,但这只是重复其他答案中已经给出的细节。此外,这个答案没有解释为什么它有用。如果还解释了这段代码如何回答用户的问题,这段代码会更有用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-29
        • 2019-06-13
        相关资源
        最近更新 更多