On Wednesday, 1 May 2024 at 15:18:03 UTC, Steven Schveighoffer wrote:
> On Wednesday, 1 May 2024 at 01:09:33 UTC, Liam McGillivray wrote:
> This is presumably such a common task that I'm surprised it isn't easy to find the answer by searching;
Is there a standard library function that removes all elements from a dynamic array that matches an input argument?
In std.array
there's the replace
function which is supposed to replace all occurrences that match an input with another. It seems to work as described on strings, but I get compiler errors when using it on other array types. I've tried using it to replace occurrences of a certain object in an array with []
in order to remove all occurrences, but it's not allowed.
Is there a Phobos function that does what I want? It would be crazy if there isn't.
remove
https://dlang.org/phobos/std_algorithm_mutation.html#remove
arr = arr.remove!(v => shouldBeRemoved(v));
Why the reassignment? Because remove
removes elements in place, and does not change the range extents. It returns the portion of the range that contains the unremoved elements.
So to give an example:
auto arr = [1, 2, 3, 4, 5];
auto result = arr.remove!(i => i % 2 == 1); // remove odd elements
assert(result == [2, 4]);
// first 2 are the slice that is stored in result
// the last three are leftovers.
assert(arr == [2, 4, 3, 4, 5]);
-Steve
In case anyone comes upon this in a search, I wanted to point out a couple dangers of using remove. The first is that it mutates arr, as shown in Steve's example. The second is
result[0] = 4;
assert(result == [4, 4]);
assert(arr == [2, 4, 3, 4, 5]); // Fails
arr[0] = 2;
assert(result == [4, 4]); // Fails
Any future changes you make to result or arr change the other. You can use remove to avoid the allocation of a new array, but you better be sure you never read or modify the original array again. If you use filter
auto result = arr.filter!(i => i % 2 == 0).array;
arr is unchanged and you can use arr and result as you want.