如何删除数组中选定的元素?

15

我有一个作业,需要从数组中删除一个选择的元素,于是我想出了以下代码:

strInput = Console.ReadLine();
for (int i = 0; i < intAmount; i++)
{
    if (strItems[i] == strInput)
    {
        strItems[i] = null;
        for (int x = 0; x < intAmount-i; x++)
        {
            i = i + 1;
            strItems[i - 1] = strItems[i];
        }
        intAmount = intAmount - 1;
    }
}

问题在于,假设我有一个数组[1,2,3,4,5,],我想删除1。输出将会是[2,3,4,5,5]。当我选择2时也会发生这种情况,但是选择其他数字时不会。

我做错了什么?


2
intAmountstrItems是什么?你在for循环中进行了许多索引操作,这通常是一个不好的想法。 - Cᴏʀʏ
你能澄清一下你的问题吗?你说[1,2,3,4,5],并要求删除1后得到[2,3,4,5,5]。那么你是如何选择5作为要复制到末尾的元素的呢? - ssamuel
strItems是字符串数组,intAmount是元素数量,strInput是用户选择删除的元素。 - user1033065
我没有选择5来复制,这就是我的问题所在。 - user1033065
5个回答

43

我假设您正在使用基本的字符串数组:

var strItems = new string[] { "1", "2", "3", "4", "5" };

在.NET中,该数组始终将有5个元素的长度。为了删除一个元素,您需要将其余的元素复制到新数组中并返回它。将位置上的值设置为null并不能从数组中删除它。

现在,使用LINQ之类的东西非常容易(此处未展示),或者您可以使用List<>集合来欺骗操作,像这样:

var list = new List<string>(strItems);
list.Remove("3");
strItems = list.ToArray();

但我认为这并不能让你学到什么。

第一步是找到要删除的元素的索引。您可以使用 Array.IndexOf 来帮助您完成。我们来找到中间的元素 "3":

int removeIndex = Array.IndexOf(strItems, "3");
如果未找到该元素,它将返回-1,在执行任何操作之前,请检查是否存在。
if (removeIndex >= 0)
{
     // continue...
}

最后,您需要将元素(除了我们不想要的索引处的元素)复制到一个新数组中。因此,总体上,您最终会得到像这样的内容(已注释以进行解释):

string strInput = Console.ReadLine();
string[] strItems = new string[] { "1", "2", "3", "4", "5" };

int removeIndex = Array.IndexOf(strItems, strInput);

if (removeIndex >= 0)
{
    // declare and define a new array one element shorter than the old array
    string[] newStrItems = new string[strItems.Length - 1];

    // loop from 0 to the length of the new array, with i being the position
    // in the new array, and j being the position in the old array
    for (int i = 0, j = 0; i < newStrItems.Length; i++, j++)
    {
        // if the index equals the one we want to remove, bump
        // j up by one to "skip" the value in the original array
        if (i == removeIndex)
        {
            j++;
        }

        // assign the good element from the original array to the
        // new array at the appropriate position
        newStrItems[i] = strItems[j];
    }

    // overwrite the old array with the new one
    strItems = newStrItems;
}

现在strItems将是新的数组,减去指定要移除的值。


哇!多么完整且详细的回答! - Gabe

4
在C#中,数组是固定大小的 - 一旦初始化,您只能修改项目,但是您不能添加或删除项目。如果您想从集合中删除一个项目,有两个选择:
1.) 创建一个新数组,其中包含原始数组中除您要删除的项目之外的所有成员。
2.) 使用可调整大小并允许添加或删除项的集合类型,例如List(在您的情况下为List)。如果您的集合不是静态的,这就是您在“现实世界”中要做的事情。

3
在你的具体实现中,我认为你错过了一个break;语句,在内部循环完成后应该退出外部循环。将null赋值给变量根本没有用。
如果列表只是数字列表,为什么要使用字符串?如果是这种情况,请直接使用整数。
你的练习似乎要求类似于这样的操作,如果你只需要删除一个元素。
public bool MyDelete(int[] array, int value) // Easy to do for strings too.
{
    bool found = false;
    for (int i = 0; i < array.Length; ++i)
    {
        if (found)
        {
            array[i - 1] = array[i];
        }
        else if (array[i] == value)
        {
            found = true;
        }
    }
    return found;
}

如果找到了指定的值,此函数将返回 true;否则返回 false。它将按照您在示例中描述的方式移动所有项,但它不会改变数组的大小。

数组是固定大小的。您不能更改数组的大小,语言不允许这样做。数组始终是固定大小的!

要从数组中删除项,您应该执行以下操作:

public static T[] RemoveAt<T>(T[] array, int index) // hope there are not bugs, wrote by scratch.
{
    int count = array.Length - 1;
    T[] result = new T[count];

    if (index > 0)
        Array.Copy(array, 0, result, 0, index - 1);
    if (index < size)
        Array.Copy(array, index + 1, result, index, size - index);

    return result;
}

...
strItems = RemoveAt(strItems, index);

该函数将创建一个新数组,其中包含除您指定索引处的元素外的所有元素。
那么,为什么有人会这样做而不是使用List或Dictionary或者其他呢?可以直接使用List而不使用数组。

3
可以使用Except方法来过滤数据。
AllData = {10, 30, 20, 50}

FilterData = {30, 20}

Result = AllData.Except(​FilterData) 

结果将会是{10, 50}


1
  • 数组是固定大小的,你不能缩短它们的长度而不创建一个新的数组。你能做的只是存储数组中有效元素的长度(即在你移除1后,长度为4)。

    此外,如果你的数组元素顺序不重要,你可以交换第一个和最后一个元素,而不是将每个元素在被移除的那个元素之后向前移动1个位置。

  • 使用集合(如ArrayList)是使用数组的替代方案,它会处理调整大小、删除和保持其中项数的计数等问题,还有更多功能。

  • 然而,由于这是作业,你可能必须使用数组。要么使用变量来跟踪长度,而不是使用array.length,要么每次想要改变大小时都创建一个新的数组。如果你不必使用数组,则可以查看C#中可用的集合。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接