从D中的数组中删除给定值的所有匹配项

从D中的数组中删除给定值的所有匹配项,d,D,假设我有一个数组。我想删除数组中具有给定值的所有元素。有人知道怎么做吗?我试图删除的值可能会出现多次,并且数组不一定要排序。我更喜欢就地筛选数组,而不是创建新数组。例如,从数组[1,2,3,2,4]中删除值2应产生结果[1,3,4] 这是我能想到的最好的办法: T[] without(T)(T[] stuff, T thingToExclude) { auto length = stuff.length; T[] result; foreach (thing; stuff

假设我有一个数组。我想删除数组中具有给定值的所有元素。有人知道怎么做吗?我试图删除的值可能会出现多次,并且数组不一定要排序。我更喜欢就地筛选数组,而不是创建新数组。例如,从数组
[1,2,3,2,4]
中删除值
2
应产生结果
[1,3,4]

这是我能想到的最好的办法:

T[] without(T)(T[] stuff, T thingToExclude) {
    auto length = stuff.length;
    T[] result;
    foreach (thing; stuff) {
        if (thing != thingToExclude) {
            result ~= thing;
        }
    }
    return result;
}

stuff = stuff.without(thingToExclude);
writeln(stuff);
这似乎是不必要的复杂和低效。有没有更简单的方法?我查看了标准库中的模块,希望找到一些有用的东西,但是看起来它可以实现我想要的功能的所有东西都有问题。以下是一些我尝试过但没有成功的例子:

import std.stdio, std.algorithm, std.conv;

auto stuff = [1, 2, 3, 2, 4];
auto thingToExclude = 2;

/*  Works fine with a hard-coded constant but compiler throws an error when
    given a value unknowable by the compiler:
    variable thingToExclude cannot be read at compile time */
stuff = filter!("a != " ~ to!string(thingToExclude))(stuff);
writeln(stuff);

/*  Works fine if I pass the result directly to writeln but compiler throws
    an error if I try assigning it to a variable such as stuff:
    cannot implicitly convert expression (filter(stuff)) of type FilterResult!(__lambda2,int[]) to int[] */
stuff = filter!((a) { return a != thingToExclude; })(stuff);
writeln(stuff);

/*  Mysterious error from compiler:
    template to(A...) if (!isRawStaticArray!(A)) cannot be sliced with [] */
stuff = to!int[](filter!((a) { return a != thingToExclude; })(stuff));
writeln(stuff);

因此,如何在不知道索引出现位置的情况下从数组中删除所有出现的值?std.algorithm.filter与您想要的非常接近:您的第二次尝试很好

您可以将其分配给新变量,也可以对其使用array()函数

auto stuffWithoutThing = filter!((a) { return a != thingToExclude; })(stuff);
// use stuffWithoutThing

第一个不创建新数组。它只是在过滤掉给定对象的情况下提供对对象的迭代


第二个将为新数组分配内存以保存内容。必须导入模块才能使其工作。

如果要删除值,可以使用“删除”

auto stuffWithoutThing = remove!((a) { return a == thingToExclude; })(stuff);

这不会分配一个新数组,但会在适当的位置工作,请注意,
stuff
范围需要是可变的

查找函数remove in。有两种策略-稳定和不稳定,这取决于您是否希望其余元素保持其相对位置。这两种策略都在适当的位置运行,并且具有O(n)复杂性。不稳定版本的写入次数较少。

上次尝试的问题是运算符优先级:
to!int[]
实例化为(T)
模板,然后应用
[]
,即切片操作符。如果要将括号作为目标类型的一部分,则需要使用parens:
to!(int[])(…)
。它仍然不起作用,但在语义上是正确的。我做了一些小的修改,现在你的帖子正好描述了我想做的事情。谢谢。您说“这不会分配新阵列,但会在适当的位置工作”。你这是什么意思?这会对
stuff
数组进行更改吗?如果是这样,那么在没有任何东西的情况下分配给
填充物的意义是什么?是的,它会对填充物进行更改,分配的意义是让您知道填充物阵列的新长度为什么我必须分配才能知道长度?为什么我不能检查
stuff
的长度呢?从文档中可以看出:“原始数组的长度保持不变,因为std.algorithm中的所有函数都只更改内容,而不更改拓扑结构。”因此,换句话说,它将对内容进行混洗,但不会修改原始容器。所发生的情况是,它将一个新的片段返回到原始数组中-新片段显示新的长度,而原始片段保持不变。
auto stuffWithoutThing = remove!((a) { return a == thingToExclude; })(stuff);