5

假设我有一个数组。我想删除数组中具有给定值的所有元素。有谁知道如何做到这一点?我试图删除的值可能不止一次出现,并且数组不一定是排序的。我宁愿就地过滤数组,而不是创建一个新数组。例如,2从数组中删除值[1, 2, 3, 2, 4]应该会产生结果[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);

这似乎不必要地复杂和低效。有没有更简单的方法?我查看了标准库中的std.algorithm模块,希望能找到一些有用的东西,但看起来它会做我想要的一切都是有问题的。以下是我尝试过但不起作用的一些示例:

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);

那么,如何在不知道它们出现的索引的情况下从数组中删除所有出现的值?

4

3 回答 3

10

std.algorithm.filter 非常接近您想要的:您的第二次尝试很好。

您需要将其分配给新变量或对其使用 array() 函数。

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

或者

stuff = array(filter!((a) { return a != thingToExclude; })(stuff));

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

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

于 2012-12-27T18:27:20.697 回答
5

在http://dlang.org/phobos/std_algorithm.html中查找函数删除。有两种策略 - 稳定和不稳定,具体取决于您是否希望剩余元素保持其相对位置。这两种策略都在原地运行并且具有 O(n) 复杂性。不稳定的版本执行较少的写入。

于 2012-12-28T15:08:46.560 回答
3

如果要删除可以使用的值 remove

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

这不会分配一个新的数组,而是在原地工作,注意stuff范围需要是可变的

于 2012-12-27T20:10:19.600 回答