【问题标题】:Removing an item from an array in C# [duplicate]从C#中的数组中删除一个项目[重复]
【发布时间】:2016-12-21 20:59:56
【问题描述】:
 Random rand = new Random();
        var list = new object[] { 1, 2, 3, "A", "B", "C" };
        object item = list[rand.Next(0, list.Length)];

我想返回 item 然后将其从 list[]

中删除

【问题讨论】:

  • 可以通过分配一个标记值(即 null,并可能滑动其他值)来“删除”该项目,但是 在 .NET 中无法更改数组的大小我>。可以创建一个新数组 .. 这就是说,List(或更改可变要求)可能是正在寻找的东西。 List 在内部使用数组,根据需要创建更大的数组和滑动值。
  • 数组不是这样工作的。您需要将数组(减去已删除的元素)复制到长度少一个的新数组中。但这非常低效,这就是List<T> 存在的原因。除非数组具有不会改变的固定长度,否则请改用List

标签: c#


【解决方案1】:

你不能。请改用List<object>

var list = new List<Object> { 1, 2, 3, "A", "B", "C" };

var list = (new object[] { 1, 2, 3, "A", "B", "C" }).ToList();

甚至

var list = new List<Object>(new object[] { 1, 2, 3, "A", "B", "C" });

然后删除一个项目(注意Length 变为Count):

int idx = rand.Next(0, list.Count);

object item = list[idx];

list.RemoveAt(idx);

还有一个 Remove 方法:

list.Remove(item);

如果您知道列表中没有重复项(例如这个),那也没关系。

从数组中“删除”一项最接近的方法是在没有它的情况下创建一个新数组——当然不值得这么麻烦。

List&lt;T&gt; 比数组更通用,所以我们一般用它来代替。

【讨论】:

  • List 有一个 .Remove() 可以使用。
  • @Bauss - 如果您已经有了索引,那么应该使用它来提高效率。所以是的,它有一个 .Remove() 方法,但在这种情况下,RemoveAt 是首选。
  • @Bauss 是的。他们也可以有重复的项目(尽管在这种情况下显然不是),无论如何,因为我们是通过索引来识别项目,所以我想我会用它来运行。但我也添加了您的建议。
【解决方案2】:

你必须销毁(忘记)并重新创建数组。

Random rand = new Random();
var list = new object[] { 1, 2, 3, "A", "B", "C" };
var index = rand.Next(0, list.Length);
object item = list[index];
list = list.Where((x, y) => y != index).ToArray(); // create new array and reassign to the existing reference
return item;

虽然没有充分的理由这样做,但请改用List&lt;T&gt;。这是使用List&lt;object&gt;的相同代码

Random rand = new Random();
var list = new List<object> { 1, 2, 3, "A", "B", "C" };
var index = rand.Next(0, list.Count);
object item = list[index];
list.RemoveAt(index);
return item;

【讨论】:

    【解决方案3】:

    这里有一些错误信息。我同意您应该使用列表,但是人们忘记了列表只是环绕数组。

    基本上你可以像这样从数组中删除:

    void Remove<T>(ref T[] source, T value)
        where T : IComparable
    {
        var newArray = new T[source.Length];
        var index = 0;
    
        foreach (var item in source)
        {
            if (item.CompareTo(value) == 0) continue;
    
            newArray[index]  = item;
            index++;
        }
    
        Array.Resize(ref newArray, index);
        source = newArray;
    }
    

    使用示例:

    var array = new[] { 1, 2, 3, 4 };
    
    Remove(ref array, 2);
    
    array.Dump();
    

    它并不漂亮,但列表也不在幕后,因为数组在 .NET 中没有使用动态分配。

    【讨论】:

      【解决方案4】:

      以@Ed Plunkett 所说的话为基础。我会将您的代码更改为:

      Random rand = new Random();
      var list = new List<object> { 1, 2, 3, "A", "B", "C" };
      object item = list[rand.Next(0, list.Count - 1)];
      

      然后调用 Remove 方法删除对象。

      list.Remove(object);
      

      旁注:请注意,我更改了 rand.Next 方法的参数。如果将最大可能数设置为列表中的项目数,则可能会遇到 IndexOutOfBounds 异常。列表使用从零开始的索引,因此如果列表中有 45 个项目,最后一个实际上将位于索引 44。

      【讨论】:

        【解决方案5】:

        如果您需要具有动态长度的集合(即由于添加和/或删除项目而可能改变的长度),那么您应该使用List&lt;T&gt;。所以你的代码可能是这样的:

        Random rand = new Random();
        var list = new List<object> { 1, 2, 3, "A", "B", "C" };
        var idx = rand.Next(0, list.Count);
        object item = list[idx];
        list.RemoveAt(idx);
        

        数组应该是固定长度的。如果您需要修改数组的长度,则必须创建一个新数组(具有更新的长度)并将所有元素(减去已删除的项)复制到新数组中。这是非常低效的。在很多情况下,数组比List 更好。

        【讨论】:

          【解决方案6】:

          正如其他人提到的,您不能从数组中“删除”(更改其大小),但您可以分配一个数组对象(即 list[0] = null)并在处理数组时检查 null。

          数组很好,但实际上列表更加灵活,并允许使用“删除”方法。使用 List.Add("item") 添加项目并使用 List.Remove("item") 删除。它允许大多数其他用于大多数基本用途的数组功能,包括 List.Count、List.Distinct、List[numeral] 等。

          【讨论】:

            【解决方案7】:

            Java 有一个dynamic array class,这似乎是你想要的,但 C# 没有“内置”的完全等价物;最接近的等价物是List&lt;T&gt;(有关详细信息,请参阅this answer)。

            请记住数组是如何“在后台”工作的(我在这里稍微简化了一点) - 当您分配它时,运行时“知道”布置一定数量的连续内存空间。在 C/C++(和后来的语言通常做类似的事情)中,运行时存储指向数组中第一项的指针/引用。然后,您可以在常数时间内计算数组中任意项的内存地址 - 例如,如果第一个地址是 1000 并且地址是 32 位,则第三项将位于地址 1000 + (2 * 32) = 1064

            顺便说一句,这就是数组索引为零的原因 - 数组中第一项的地址是指向数组开头的指针/引用加上零偏移量。

            那么,问题在于,如果您删除了数组中间的某个项目,则内存位置将不再是连续的。如果您删除 someArray[3] 然后稍后尝试访问它,究竟会发生什么?它应该变成null,变成一个事实上的未初始化的内存位置,还是包含以前在someArray[4] 的任何东西?

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2019-03-15
              • 2021-02-20
              • 1970-01-01
              • 1970-01-01
              • 2014-01-16
              • 2020-03-26
              相关资源
              最近更新 更多