在C#中从数组中删除项

时间:2016-12-21 20:59:56

标签: c#

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

我想返回,然后将其从列表[]

中删除

7 个答案:

答案 0 :(得分:6)

你做不到。请改用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);

还有一种删除方法:

list.Remove(item);

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

你最接近“从数组中删除”一个项目的方法是创建一个没有它的新数组 - 当然不值得麻烦。

List<T>比数组更通用,所以我们通常使用它。

答案 1 :(得分:1)

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

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<T>。以下是使用List<object>

的相同代码
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;

答案 2 :(得分:1)

这里有一些错误的信息。我同意你应该使用一个列表,但是人们忘记了列表只是包含数组。

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

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中没有使用动态分配。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

建立@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 :(得分:0)

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

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 :(得分:0)

Java有一个dynamic array class,它看起来像你想要的,但C#没有“内置”的精确等价物;最接近的等价物是List<T>(有关详情,请参阅this answer)。

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

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

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