std.algorithm.mutation.remove
- multiple declarations
Function remove
Eliminates elements at given offsets from range
and returns the shortened
range.
Range remove(SwapStrategy s = SwapStrategy .stable, Range, Offset...)
(
Range range,
Offset offset
)
if (s != SwapStrategy .stable && isBidirectionalRange!Range && hasLvalueElements!Range && hasLength!Range && (Offset .length >= 1));
Range remove(SwapStrategy s = SwapStrategy .stable, Range, Offset...)
(
Range range,
Offset offset
)
if (s == SwapStrategy .stable && isBidirectionalRange!Range && hasLvalueElements!Range && (Offset .length >= 1));
For example, here is how to remove a single element from an array:
string[] a = [ "a", "b", "c", "d" ];
a = a .remove(1); // remove element at offset 1
assert(a == [ "a", "c", "d"]);
Note that remove
does not change the length of the original range directly;
instead, it returns the shortened range. If its return value is not assigned to
the original range, the original range will retain its original length, though
its contents will have changed:
int[] a = [ 3, 5, 7, 8 ];
assert(remove(a, 1) == [ 3, 7, 8 ]);
assert(a == [ 3, 7, 8, 8 ]);
The element at offset 1
has been removed and the rest of the elements have
shifted up to fill its place, however, the original array remains of the same
length. This is because all functions in std
only change content, not topology. The value 8
is repeated because move
was
invoked to rearrange elements, and on integers move
simply copies the source
to the destination. To replace a
with the effect of the removal, simply
assign the slice returned by remove
to it, as shown in the first example.
Multiple indices can be passed into remove
. In that case,
elements at the respective indices are all removed. The indices must
be passed in increasing order, otherwise an exception occurs.
int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
assert(remove(a, 1, 3, 5) ==
[ 0, 2, 4, 6, 7, 8, 9, 10 ]);
(Note that all indices refer to slots in the original array, not in the array as it is being progressively shortened.) Finally, any combination of integral offsets and tuples composed of two integral offsets can be passed in.
int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
assert(remove(a, 1, tuple(3, 5), 9) == [ 0, 2, 5, 6, 7, 8, 10 ]);
In this case, the slots at positions 1, 3, 4, and 9 are removed from
the array. The tuple passes in a range closed to the left and open to
the right (consistent with built-in slices), e.g. tuple(3, 5)
means indices 3
and 4
but not 5
.
If the need is to remove some elements in the range but the order of
the remaining elements does not have to be preserved, you may want to
pass SwapStrategy
to remove
.
int[] a = [ 0, 1, 2, 3 ];
assert(remove!(SwapStrategy .unstable)(a, 1) == [ 0, 3, 2 ]);
In the case above, the element at slot 1
is removed, but replaced
with the last element of the range. Taking advantage of the relaxation
of the stability requirement, remove
moved elements from the end
of the array over the slots to be removed. This way there is less data
movement to be done which improves the execution time of the function.
The function remove
works on bidirectional ranges that have assignable
lvalue elements. The moving strategy is (listed from fastest to slowest):
- If
s == SwapStrategy
, then elements are moved from the end of the range into the slots to be filled. In this case, the absolute minimum of moves is performed..unstable && isRandomAccessRange!Range && hasLength!Range && hasLvalueElements!Range - Otherwise, if
s == SwapStrategy
, then elements are still moved from the end of the range, but time is spent on advancing between slots by repeated calls to.unstable && isBidirectionalRange!Range && hasLength!Range && hasLvalueElements!Range range
..popFront - Otherwise, elements are moved
incrementally towards the front of
range
; a given element is never moved several times, but more elements are moved than in the previous cases.
Parameters
Name | Description |
---|---|
s | a SwapStrategy to determine if the original order needs to be preserved |
range | a bidirectional range with a length member |
offset | which element(s) to remove |
Returns
a range containing all of the elements of range with offset removed
Example
import std .typecons : tuple;
auto a = [ 0, 1, 2, 3, 4, 5 ];
writeln(remove!(SwapStrategy .stable)(a, 1)); // [0, 2, 3, 4, 5]
a = [ 0, 1, 2, 3, 4, 5 ];
writeln(remove!(SwapStrategy .stable)(a, 1, 3)); // [0, 2, 4, 5]
a = [ 0, 1, 2, 3, 4, 5 ];
writeln(remove!(SwapStrategy .stable)(a, 1, tuple(3, 6))); // [0, 2]
a = [ 0, 1, 2, 3, 4, 5 ];
writeln(remove!(SwapStrategy .unstable)(a, 1)); // [0, 5, 2, 3, 4]
a = [ 0, 1, 2, 3, 4, 5 ];
writeln(remove!(SwapStrategy .unstable)(a, tuple(1, 4))); // [0, 5, 4]
Function remove
Reduces the length of the
bidirectional range range
by removing
elements that satisfy pred
. If s = SwapStrategy
,
elements are moved from the right end of the range over the elements
to eliminate. If s = SwapStrategy
(the default),
elements are moved progressively to front such that their relative
order is preserved. Returns the filtered range.
Range remove(alias pred, SwapStrategy s = SwapStrategy .stable, Range)
(
Range range
)
if (isBidirectionalRange!Range && hasLvalueElements!Range);
Parameters
Name | Description |
---|---|
range | a bidirectional ranges with lvalue elements |
Returns
the range with all of the elements where pred
is true
removed
Example
static immutable base = [1, 2, 3, 2, 4, 2, 5, 2];
int[] arr = base[] .dup;
// using a string-based predicate
writeln(remove!("a == 2")(arr)); // [1, 3, 4, 5]
// The original array contents have been modified,
// so we need to reset it to its original state.
// The length is unmodified however.
arr[] = base[];
// using a lambda predicate
writeln(remove!(a => a == 2)(arr)); // [1, 3, 4, 5]