【问题标题】:How to delete an element from an array in D如何从D中的数组中删除一个元素
【发布时间】:2011-05-16 08:53:34
【问题描述】:

在 D 中将元素 x 连接到数组 items 很容易,就好像它是一个数组列表:

arr ~= x;

但是我如何删除items 中索引i 的元素?

(警告:如果我删除一个元素然后添加一个新元素,则数组不得重新分配。所以简单的切片将不起作用。)


更新:

根据 Cyber​​Shadow 对使用 assumeSafeAppend 的回答,我编写了以下代码:

static void removeAt(T)(ref T[] arr, size_t index)
{
    foreach (i, ref item; arr[index .. $ - 1])
        item = arr[i + 1];
    arr = arr[0 .. $ - 1];
    arr.assumeSafeAppend();
}

但是,当您遇到以下情况时会出现问题:

auto superArr = [0, 1, 2, 3, 4]; //Must not be modified
auto arr = superArr[0 .. $ - 1];
writeln(superArr);
arr.removeAt(0);    //Should copy the slice and modify the copy
writeln(superArr);  //but obviously doesn't

如果一个元素从切片中移除,切片的基本数组应该被修改;相反,需要复制切片。

但我无法知道一个数组是否是一个更大数组的一部分......所以这不起作用。

有什么建议吗?

【问题讨论】:

  • 更新了我对您的编辑的回答。
  • @Cyber​​Shadow:那是so hacky,但无论如何我都会使用它。 xD 谢谢!
  • @Cyber​​Shadow:等等,实际上,我刚刚尝试过,但它似乎不起作用......你确定它是这样做的吗?
  • 对我有用,但是(正如我刚刚意识到的)如果切片位于数组的末尾,它将无法工作......没关系:/
  • @Cyber​​Shadow:哦,我明白了...啊,这比我想象的要丑得多很多...:\

标签: arrays d


【解决方案1】:

复制我在digitalmars.D上的回答(感谢转发):

如前所述,std.algorithm.remove 可能会有所帮助。您可能想特别查看它的三个功能:(a)一次删除多个偏移量,例如remove(a, 0, 4) 删除第一个和第五个元素,(b) 您可以删除子范围,例如remove(a, tuple(1, 3)) 删除第二个到第四个元素,以及 (c) 如果您不关心删除后元素的剩余顺序,您可能需要查看不稳定的删除,这相当重要减少工作量。

安德烈

【讨论】:

  • 感谢您的回答! :) 与我在新闻组上发布的评论相同,但...remove 似乎并没有真正正确地修改数组(实际上删除任何内容仍会导致添加时重新分配)。 :\
  • 如何删除一组索引?比如'remove(a, [0, 2, 3])'?
【解决方案2】:

(警告:如果我删除一个元素然后添加一个新元素,则数组不得重新分配。所以简单的切片将不起作用。)

assumeSafeAppend 函数将告诉运行时在追加数组时不要重新分配数组(即用户确认没有其他切片可能会被追加踩踏)。

remove from std.algorithm 进行就地删除。如果你使用std.container,还有Array.linearRemove

【讨论】:

  • +1 for remove,尽管我上次检查实现有点慢。因此我经常使用memmove
  • @Cyber​​Shadow:我不认为 removelinearRemove 可以完成这项工作(第一个会在添加新元素时导致重新分配,不是吗?第二个不会集成使用语言和 GC),但我 认为 assumeSafeAppend 非常有帮助,如果可行,我会接受。 :) +1
  • @Cyber​​Shadow:不,assumeSafeAppend 似乎有点棘手:它仅在您从一个不是另一个数组切片的数组中删除时才有效;否则,您可以覆盖超级数组。有没有办法检测一个数组是否是更大数组的一部分?
  • std.container.Array 没有remove。当您提到语言/GC 集成时,不确定您到底在寻找什么,但 std.container.Array 是引用计数的,并且会重载索引和切片运算符。
  • @Cyber​​Shadow:如果我在Array 中存储指向 GC 堆的指针(例如对象引用),G​​C 怎么知道要扫描它? AFAIK Array 不能只替换这样的常规数组。
【解决方案3】:

如果顺序不重要,您可以将最后一个元素复制到要删除的位置,然后将数组长度减一。

【讨论】:

  • 抱歉,顺序很重要。 :(
【解决方案4】:

如果您只想删除第一个或最后一个元素,请使用切片:

array = array [1..$]
array = array [0..$-1]

或者一种也适用于中间人的通用方式:

array = array [0..unlucky] ~ array [unlucky+1..$]

如果元素不是结构、浮点数、整数等基本元素,那么数组就是指针的隐式数组,这是一种有效的操作。

【讨论】:

    【解决方案5】:

    没有自动执行此操作的方法,您必须将数组项随机排列,重置 .length,然后进行连接。

    【讨论】:

      猜你喜欢
      • 2018-07-13
      • 2020-10-25
      • 2012-06-19
      • 2010-10-04
      • 1970-01-01
      • 2022-01-16
      • 2012-04-19
      • 2014-12-09
      • 1970-01-01
      相关资源
      最近更新 更多