/D

# std.algorithm.mutation

This is a submodule of `std.algorithm`. It contains generic mutation algorithms.

Cheat Sheet
Function Name Description
`bringToFront` If `a = [1, 2, 3]` and `b = [4, 5, 6, 7]`, `bringToFront(a, b)` leaves `a = [4, 5, 6]` and `b = [7, 1, 2, 3]`.
`copy` Copies a range to another. If `a = [1, 2, 3]` and `b = new int`, then `copy(a, b)` leaves `b = [1, 2, 3, 0, 0]` and returns `b[3 .. \$]`.
`fill` Fills a range with a pattern, e.g., if `a = new int`, then `fill(a, 4)` leaves `a = [4, 4, 4]` and `fill(a, [3, 4])` leaves `a = [3, 4, 3]`.
`initializeAll` If `a = [1.2, 3.4]`, then `initializeAll(a)` leaves `a = [double.init, double.init]`.
`move` `move(a, b)` moves `a` into `b`. `move(a)` reads `a` destructively when necessary.
`moveEmplace` Similar to `move` but assumes `target` is uninitialized.
`moveAll` Moves all elements from one range to another.
`moveEmplaceAll` Similar to `moveAll` but assumes all elements in `target` are uninitialized.
`moveSome` Moves as many elements as possible from one range to another.
`moveEmplaceSome` Similar to `moveSome` but assumes all elements in `target` are uninitialized.
`remove` Removes elements from a range in-place, and returns the shortened range.
`reverse` If `a = [1, 2, 3]`, `reverse(a)` changes it to `[3, 2, 1]`.
`strip` Strips all leading and trailing elements equal to a value, or that satisfy a predicate. If `a = [1, 1, 0, 1, 1]`, then `strip(a, 1)` and `strip!(e => e == 1)(a)` returns ``.
`stripLeft` Strips all leading elements equal to a value, or that satisfy a predicate. If `a = [1, 1, 0, 1, 1]`, then `stripLeft(a, 1)` and `stripLeft!(e => e == 1)(a)` returns `[0, 1, 1]`.
`stripRight` Strips all trailing elements equal to a value, or that satisfy a predicate. If `a = [1, 1, 0, 1, 1]`, then `stripRight(a, 1)` and `stripRight!(e => e == 1)(a)` returns `[1, 1, 0]`.
`swap` Swaps two values.
`swapAt` Swaps two values by indices.
`swapRanges` Swaps all elements of two ranges.
`uninitializedFill` Fills a range (assumed uninitialized) with a value.
Authors:
Andrei Alexandrescu
Source
std/algorithm/mutation.d
size_t bringToFront(InputRange, ForwardRange)(InputRange front, ForwardRange back)
Constraints: if (isInputRange!InputRange && isForwardRange!ForwardRange);

`bringToFront` takes two ranges `front` and `back`, which may be of different types. Considering the concatenation of `front` and `back` one unified range, `bringToFront` rotates that unified range such that all elements in `back` are brought to the beginning of the unified range. The relative ordering of elements in `front` and `back`, respectively, remains unchanged.

The `bringToFront` function treats strings at the code unit level and it is not concerned with Unicode character integrity. `bringToFront` is designed as a function for moving elements in ranges, not as a string function.

Performs Ο(`max(front.length, back.length)`) evaluations of `swap`.

The `bringToFront` function can rotate elements in one buffer left or right, swap buffers of equal length, and even move elements across disjoint buffers of different types and different lengths.

Preconditions
Either `front` and `back` are disjoint, or `back` is reachable from `front` and `front` is not reachable from `back`.
Parameters:
 InputRange `front` an input range ForwardRange `back` a forward range
Returns:
The number of elements brought to the front, i.e., the length of `back`.
STL's `rotate`
Examples:
The simplest use of `bringToFront` is for rotating elements in a buffer. For example:
```auto arr = [4, 5, 6, 7, 1, 2, 3];
auto p = bringToFront(arr[0 .. 4], arr[4 .. \$]);
writeln(p); // arr.length - 4
writeln(arr); // [1, 2, 3, 4, 5, 6, 7]
```
Examples:
The `front` range may actually "step over" the `back` range. This is very useful with forward ranges that cannot compute comfortably right-bounded subranges like `arr[0 .. 4]` above. In the example below, `r2` is a right subrange of `r1`.
```import std.algorithm.comparison : equal;
import std.container : SList;
import std.range.primitives : popFrontN;

auto list = SList!(int)(4, 5, 6, 7, 1, 2, 3);
auto r1 = list[];
auto r2 = list[]; popFrontN(r2, 4);
assert(equal(r2, [ 1, 2, 3 ]));
bringToFront(r1, r2);
assert(equal(list[], [ 1, 2, 3, 4, 5, 6, 7 ]));
```
Examples:
Elements can be swapped across ranges of different types:
```import std.algorithm.comparison : equal;
import std.container : SList;

auto list = SList!(int)(4, 5, 6, 7);
auto vec = [ 1, 2, 3 ];
bringToFront(list[], vec);
assert(equal(list[], [ 1, 2, 3, 4 ]));
assert(equal(vec, [ 5, 6, 7 ]));
```
Examples:
Unicode integrity is not preserved:
```import std.string : representation;
auto ar = representation("a".dup);
auto br = representation("ç".dup);

bringToFront(ar, br);

auto a = cast(char[]) ar;
auto b = cast(char[]) br;

// Illegal UTF-8
writeln(a); // "\303"
// Illegal UTF-8
writeln(b); // "\247a"
```
TargetRange copy(SourceRange, TargetRange)(SourceRange source, TargetRange target)
Constraints: if (isInputRange!SourceRange && isOutputRange!(TargetRange, ElementType!SourceRange));

Copies the content of `source` into `target` and returns the remaining (unfilled) part of `target`.

Preconditions
`target` shall have enough room to accommodate the entirety of `source`.
Parameters:
 SourceRange `source` an input range TargetRange `target` an output range
Returns:
The unfilled part of target
Examples:
```int[] a = [ 1, 5 ];
int[] b = [ 9, 8 ];
int[] buf = new int[](a.length + b.length + 10);
auto rem = a.copy(buf);    // copy a into buf
rem = b.copy(rem);         // copy b into remainder of buf
writeln(buf[0 .. a.length + b.length]); // [1, 5, 9, 8]
assert(rem.length == 10);   // unused slots in buf
```
Examples:
As long as the target range elements support assignment from source range elements, different types of ranges are accepted:
```float[] src = [ 1.0f, 5 ];
double[] dest = new double[src.length];
src.copy(dest);
```
Examples:
To copy at most `n` elements from a range, you may want to use `std.range.take`:
```import std.range;
int[] src = [ 1, 5, 8, 9, 10 ];
auto dest = new int[](3);
src.take(dest.length).copy(dest);
writeln(dest); // [1, 5, 8]
```
Examples:
To copy just those elements from a range that satisfy a predicate, use `filter`:
```import std.algorithm.iteration : filter;
int[] src = [ 1, 5, 8, 9, 10, 1, 2, 0 ];
auto dest = new int[src.length];
auto rem = src
.filter!(a => (a & 1) == 1)
.copy(dest);
writeln(dest[0 .. \$ - rem.length]); // [1, 5, 9, 1]
```
Examples:
`std.range.retro` can be used to achieve behavior similar to STL's `copy_backward`':
```import std.algorithm, std.range;
int[] src = [1, 2, 4];
int[] dest = [0, 0, 0, 0, 0];
src.retro.copy(dest.retro);
writeln(dest); // [0, 0, 1, 2, 4]
```
void fill(Range, Value)(auto ref Range range, auto ref Value value)
Constraints: if (isInputRange!Range && is(typeof(range.front = value)) || isSomeChar!Value && is(typeof(range[] = value)));

void fill(InputRange, ForwardRange)(InputRange range, ForwardRange filler)
Constraints: if (isInputRange!InputRange && (isForwardRange!ForwardRange || isInputRange!ForwardRange && isInfinite!ForwardRange) && is(typeof(InputRange.init.front = ForwardRange.init.front)));

Assigns `value` to each element of input range `range`.

Alternatively, instead of using a single `value` to fill the `range`, a `filter` forward range can be provided. The length of `filler` and `range` do not need to match, but `filler` must not be empty.

Parameters:
 Range `range` An input range that exposes references to its elements and has assignable elements Value `value` Assigned to each element of range ForwardRange `filler` A forward range representing the fill pattern.
Throws:
If `filler` is empty.
`uninitializedFill` `initializeAll`
Examples:
```int[] a = [ 1, 2, 3, 4 ];
fill(a, 5);
writeln(a); // [5, 5, 5, 5]
```
Examples:
```int[] a = [ 1, 2, 3, 4, 5 ];
int[] b = [ 8, 9 ];
fill(a, b);
writeln(a); // [8, 9, 8, 9, 8]
```
void initializeAll(Range)(Range range)
Constraints: if (isInputRange!Range && hasLvalueElements!Range && hasAssignableElements!Range);

void initializeAll(Range)(Range range)
Constraints: if (is(Range == char[]) || is(Range == wchar[]));

Initializes all elements of `range` with their `.init` value. Assumes that the elements of the range are uninitialized.

Parameters:
 Range `range` An input range that exposes references to its elements and has assignable elements
`fill` `uninitializeFill`
Examples:
```import core.stdc.stdlib : malloc, free;

struct S
{
int a = 10;
}

auto s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5];
initializeAll(s);
writeln(s); // [S(10), S(10), S(10), S(10), S(10)]

scope(exit) free(s.ptr);
```
void move(T)(ref T source, ref T target);

T move(T)(return ref scope T source);

Moves `source` into `target`, via a destructive copy when necessary.

If `T` is a struct with a destructor or postblit defined, source is reset to its `.init` value after it is moved into target, otherwise it is left unchanged.

Preconditions
If source has internal pointers that point to itself and doesn't define opPostMove, it cannot be moved, and will trigger an assertion failure.
Parameters:
 T `source` Data to copy. T `target` Where to copy into. The destructor, if any, is invoked before the copy is performed.
Examples:
For non-struct types, `move` just performs `target = source`:
```Object obj1 = new Object;
Object obj2 = obj1;
Object obj3;

move(obj2, obj3);
assert(obj3 is obj1);
// obj2 unchanged
assert(obj2 is obj1);
```
Examples:
```// Structs without destructors are simply copied
struct S1
{
int a = 1;
int b = 2;
}
S1 s11 = { 10, 11 };
S1 s12;

move(s11, s12);

writeln(s12); // S1(10, 11)
writeln(s11); // s12

// But structs with destructors or postblits are reset to their .init value
// after copying to the target.
struct S2
{
int a = 1;
int b = 2;

~this() pure nothrow @safe @nogc { }
}
S2 s21 = { 3, 4 };
S2 s22;

move(s21, s22);

writeln(s21); // S2(1, 2)
writeln(s22); // S2(3, 4)
```
Examples:
Non-copyable structs can still be moved:
```struct S
{
int a = 1;
@disable this(this);
~this() pure nothrow @safe @nogc {}
}
S s1;
s1.a = 2;
S s2 = move(s1);
writeln(s1.a); // 1
writeln(s2.a); // 2
```
Examples:
`opPostMove` will be called if defined:
```struct S
{
int a;
void opPostMove(const ref S old)
{
writeln(a); // old.a
a++;
}
}
S s1;
s1.a = 41;
S s2 = move(s1);
writeln(s2.a); // 42
```
pure @system void moveEmplace(T)(ref T source, ref T target);

Similar to `move` but assumes `target` is uninitialized. This is more efficient because `source` can be blitted over `target` without destroying or initializing it first.

Parameters:
 T `source` value to be moved into target T `target` uninitialized value to be filled by source
Examples:
```static struct Foo
{
pure nothrow @nogc:
this(int* ptr) { _ptr = ptr; }
~this() { if (_ptr) ++*_ptr; }
int* _ptr;
}

int val;
Foo foo1 = void; // uninitialized
auto foo2 = Foo(&val); // initialized
assert(foo2._ptr is &val);

// Using `move(foo2, foo1)` would have an undefined effect because it would destroy
// the uninitialized foo1.
// moveEmplace directly overwrites foo1 without destroying or initializing it first.
moveEmplace(foo2, foo1);
assert(foo1._ptr is &val);
assert(foo2._ptr is null);
writeln(val); // 0
```
InputRange2 moveAll(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
Constraints: if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(move(src.front, tgt.front))));

Calls `move(a, b)` for each element `a` in `src` and the corresponding element `b` in `tgt`, in increasing order.

Preconditions
`walkLength(src) <= walkLength(tgt)`. This precondition will be asserted. If you cannot ensure there is enough room in `tgt` to accommodate all of `src` use `moveSome` instead.
Parameters:
 InputRange1 `src` An input range with movable elements. InputRange2 `tgt` An input range with elements that elements from `src` can be moved into.
Returns:
The leftover portion of `tgt` after all elements from `src` have been moved.
Examples:
```int a = [ 1, 2, 3 ];
int b;
assert(moveAll(a[], b[]) is b[3 .. \$]);
writeln(a[]); // b[0 .. 3]
int cmp = [ 1, 2, 3 ];
writeln(a[]); // cmp[]
```
@system InputRange2 moveEmplaceAll(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
Constraints: if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(moveEmplace(src.front, tgt.front))));

Similar to `moveAll` but assumes all elements in `tgt` are uninitialized. Uses `moveEmplace` to move elements from `src` over elements from `tgt`.

Examples:
```static struct Foo
{
~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
int* _ptr;
}
int refs = [0, 1, 2];
Foo src = [Foo(&refs), Foo(&refs), Foo(&refs)];
Foo dst = void;

auto tail = moveEmplaceAll(src[], dst[]); // move 3 value from src over dst
assert(tail.length == 2); // returns remaining uninitialized values
initializeAll(tail);

import std.algorithm.searching : all;
assert(src[].all!(e => e._ptr is null));
assert(dst[0 .. 3].all!(e => e._ptr !is null));
```
Tuple!(InputRange1, InputRange2) moveSome(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
Constraints: if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(move(src.front, tgt.front))));

Calls `move(a, b)` for each element `a` in `src` and the corresponding element `b` in `tgt`, in increasing order, stopping when either range has been exhausted.

Parameters:
 InputRange1 `src` An input range with movable elements. InputRange2 `tgt` An input range with elements that elements from `src` can be moved into.
Returns:
The leftover portions of the two ranges after one or the other of the ranges have been exhausted.
Examples:
```int a = [ 1, 2, 3, 4, 5 ];
int b;
assert(moveSome(a[], b[]) is a[3 .. \$]);
writeln(a[0 .. 3]); // b
writeln(a); // [1, 2, 3, 4, 5]
```
@system Tuple!(InputRange1, InputRange2) moveEmplaceSome(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
Constraints: if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(move(src.front, tgt.front))));

Same as `moveSome` but assumes all elements in `tgt` are uninitialized. Uses `moveEmplace` to move elements from `src` over elements from `tgt`.

Examples:
```static struct Foo
{
~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
int* _ptr;
}
int refs = [0, 1, 2, 3];
Foo src = [Foo(&refs), Foo(&refs), Foo(&refs), Foo(&refs)];
Foo dst = void;

auto res = moveEmplaceSome(src[], dst[]);
writeln(res.length); // 2

import std.algorithm.searching : all;
assert(src[0 .. 3].all!(e => e._ptr is null));
assert(src._ptr !is null);
assert(dst[].all!(e => e._ptr !is null));
```
enum SwapStrategy: int;

Defines the swapping strategy for algorithms that need to swap elements in a range (such as partition and sort). The strategy concerns the swapping of elements that are not the core concern of the algorithm. For example, consider an algorithm that sorts `[ "abc", "b", "aBc" ]` according to `toUpper(a) < toUpper(b)`. That algorithm might choose to swap the two equivalent strings `"abc"` and `"aBc"`. That does not affect the sorting since both `["abc", "aBc", "b" ]` and `[ "aBc", "abc", "b" ]` are valid outcomes.

Some situations require that the algorithm must NOT ever change the relative ordering of equivalent elements (in the example above, only `[ "abc", "aBc", "b" ]` would be the correct result). Such algorithms are called stable. If the ordering algorithm may swap equivalent elements discretionarily, the ordering is called unstable.

Yet another class of algorithms may choose an intermediate tradeoff by being stable only on a well-defined subrange of the range. There is no established terminology for such behavior; this library calls it semistable.

Generally, the `stable` ordering strategy may be more costly in time and/or space than the other two because it imposes additional constraints. Similarly, `semistable` may be costlier than `unstable`. As (semi-)stability is not needed very often, the ordering algorithms in this module parameterized by `SwapStrategy` all choose `SwapStrategy.unstable` as the default.

Examples:
```int[] a = [0, 1, 2, 3];
writeln(remove!(SwapStrategy.stable)(a, 1)); // [0, 2, 3]
a = [0, 1, 2, 3];
writeln(remove!(SwapStrategy.unstable)(a, 1)); // [0, 3, 2]
```
Examples:
```import std.algorithm.sorting : partition;

// Put stuff greater than 3 on the left
auto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
writeln(partition!(a => a > 3, SwapStrategy.stable)(arr)); // [1, 2, 3]
writeln(arr); // [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]

arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
writeln(partition!(a => a > 3, SwapStrategy.semistable)(arr)); // [2, 3, 1]
writeln(arr); // [4, 5, 6, 7, 8, 9, 10, 2, 3, 1]

arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
writeln(partition!(a => a > 3, SwapStrategy.unstable)(arr)); // [3, 2, 1]
writeln(arr); // [10, 9, 8, 4, 5, 6, 7, 3, 2, 1]
```
unstable

Allows freely swapping of elements as long as the output satisfies the algorithm's requirements.

semistable

In algorithms partitioning ranges in two, preserve relative ordering of elements only to the left of the partition point.

stable

Preserve the relative ordering of elements to the largest extent allowed by the algorithm's requirements.

Range remove(SwapStrategy s = SwapStrategy.stable, Range, Offset...)(Range range, Offset offset)
Constraints: if (Offset.length >= 1 && allSatisfy!(isValidIntegralTuple, Offset));

Eliminates elements at given offsets from `range` and returns the shortened range.

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.algorithm` 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.)

Tuples of two integral offsets can be used to remove an indices range:

```int[] a = [ 3, 4, 5, 6, 7];
assert(remove(a, 1, tuple(1, 3), 9) == [ 3, 6, 7 ]);
```

The tuple passes in a range closed to the left and open to the right (consistent with built-in slices), e.g. `tuple(1, 3)` means indices `1` and `2` but not `3`.

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.

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.unstable` 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.unstable && isRandomAccessRange!Range && hasLength!Range && hasLvalueElements!Range`, 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.
• Otherwise, if `s == SwapStrategy.unstable && isBidirectionalRange!Range && hasLength!Range && hasLvalueElements!Range`, then elements are still moved from the end of the range, but time is spent on advancing between slots by repeated calls to `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:
 s a SwapStrategy to determine if the original order needs to be preserved Range `range` a bidirectional range with a length member Offset `offset` which element(s) to remove
Returns:
A range containing all of the elements of range with offset removed.
Range remove(alias pred, SwapStrategy s = SwapStrategy.stable, Range)(Range range);

Reduces the length of the bidirectional range `range` by removing elements that satisfy `pred`. If `s = SwapStrategy.unstable`, elements are moved from the right end of the range over the elements to eliminate. If `s = SwapStrategy.stable` (the default), elements are moved progressively to front such that their relative order is preserved. Returns the filtered range.

Parameters:
 Range `range` a bidirectional ranges with lvalue elements or mutable character arrays
Returns:
the range with all of the elements where `pred` is `true` removed
Examples:
```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]
```
Range reverse(Range)(Range r)
Constraints: if (isBidirectionalRange!Range && (hasSwappableElements!Range || hasAssignableElements!Range && hasLength!Range && isRandomAccessRange!Range || isNarrowString!Range && isAssignable!(ElementType!Range)));

Reverses `r` in-place. Performs `r.length / 2` evaluations of `swap`. UTF sequences consisting of multiple code units are preserved properly.

Parameters:
 Range `r` a bidirectional range with either swappable elements, a random access range with a length member, or a narrow string
Returns:
`r`
Note
When passing a string with unicode modifiers on characters, such as `\u0301`, this function will not properly keep the position of the modifier. For example, reversing `ba\u0301d` ("bád") will result in d\u0301ab ("d́ab") instead of `da\u0301b` ("dáb").
`std.range.retro` for a lazy reverse without changing `r`
Examples:
```int[] arr = [ 1, 2, 3 ];
writeln(arr.reverse); // [3, 2, 1]
```
Examples:
```char[] arr = "hello\U00010143\u0100\U00010143".dup;
writeln(arr.reverse); // "\U00010143\u0100\U00010143olleh"
```
Range strip(Range, E)(Range range, E element)
Constraints: if (isBidirectionalRange!Range && is(typeof(range.front == element) : bool));

Range strip(alias pred, Range)(Range range)
Constraints: if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool));

Range stripLeft(Range, E)(Range range, E element)
Constraints: if (isInputRange!Range && is(typeof(range.front == element) : bool));

Range stripLeft(alias pred, Range)(Range range)
Constraints: if (isInputRange!Range && is(typeof(pred(range.front)) : bool));

Range stripRight(Range, E)(Range range, E element)
Constraints: if (isBidirectionalRange!Range && is(typeof(range.back == element) : bool));

Range stripRight(alias pred, Range)(Range range)
Constraints: if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool));

The strip group of functions allow stripping of either leading, trailing, or both leading and trailing elements.

The `stripLeft` function will strip the `front` of the range, the `stripRight` function will strip the `back` of the range, while the `strip` function will strip both the `front` and `back` of the range.

Note that the `strip` and `stripRight` functions require the range to be a `BidirectionalRange` range.

All of these functions come in two varieties: one takes a target element, where the range will be stripped as long as this element can be found. The other takes a lambda predicate, where the range will be stripped as long as the predicate returns true.

Parameters:
 Range `range` a bidirectional range or input range E `element` the elements to remove
Returns:
a Range with all of range except element at the start and end
Examples:
Strip leading and trailing elements equal to the target element.
```writeln("  foobar  ".strip(' ')); // "foobar"
writeln("00223.444500".strip('0')); // "223.4445"
writeln("ëëêéüŗōpéêëë".strip('ë')); // "êéüŗōpéê"
writeln([1, 1, 0, 1, 1].strip(1)); // 
writeln([0.0, 0.01, 0.01, 0.0].strip(0).length); // 2
```
Examples:
Strip leading and trailing elements while the predicate returns true.
```writeln("  foobar  ".strip!(a => a == ' ')()); // "foobar"
writeln("00223.444500".strip!(a => a == '0')()); // "223.4445"
writeln("ëëêéüŗōpéêëë".strip!(a => a == 'ë')()); // "êéüŗōpéê"
writeln([1, 1, 0, 1, 1].strip!(a => a == 1)()); // 
writeln([0.0, 0.01, 0.5, 0.6, 0.01, 0.0].strip!(a => a < 0.4)().length); // 2
```
Examples:
Strip leading elements equal to the target element.
```writeln("  foobar  ".stripLeft(' ')); // "foobar  "
writeln("00223.444500".stripLeft('0')); // "223.444500"
writeln("ůůűniçodêéé".stripLeft('ů')); // "űniçodêéé"
writeln([1, 1, 0, 1, 1].stripLeft(1)); // [0, 1, 1]
writeln([0.0, 0.01, 0.01, 0.0].stripLeft(0).length); // 3
```
Examples:
Strip leading elements while the predicate returns true.
```writeln("  foobar  ".stripLeft!(a => a == ' ')()); // "foobar  "
writeln("00223.444500".stripLeft!(a => a == '0')()); // "223.444500"
writeln("ůůűniçodêéé".stripLeft!(a => a == 'ů')()); // "űniçodêéé"
writeln([1, 1, 0, 1, 1].stripLeft!(a => a == 1)()); // [0, 1, 1]
writeln([0.0, 0.01, 0.10, 0.5, 0.6].stripLeft!(a => a < 0.4)().length); // 2
```
Examples:
Strip trailing elements equal to the target element.
```writeln("  foobar  ".stripRight(' ')); // "  foobar"
writeln("00223.444500".stripRight('0')); // "00223.4445"
writeln("ùniçodêéé".stripRight('é')); // "ùniçodê"
writeln([1, 1, 0, 1, 1].stripRight(1)); // [1, 1, 0]
writeln([0.0, 0.01, 0.01, 0.0].stripRight(0).length); // 3
```
Examples:
Strip trailing elements while the predicate returns true.
```writeln("  foobar  ".stripRight!(a => a == ' ')()); // "  foobar"
writeln("00223.444500".stripRight!(a => a == '0')()); // "00223.4445"
writeln("ùniçodêéé".stripRight!(a => a == 'é')()); // "ùniçodê"
writeln([1, 1, 0, 1, 1].stripRight!(a => a == 1)()); // [1, 1, 0]
writeln([0.0, 0.01, 0.10, 0.5, 0.6].stripRight!(a => a > 0.4)().length); // 3
```
pure nothrow @nogc @trusted void swap(T)(ref T lhs, ref T rhs)
Constraints: if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs))));

void swap(T)(ref T lhs, ref T rhs)
Constraints: if (is(typeof(lhs.proxySwap(rhs))));

Swaps `lhs` and `rhs`. The instances `lhs` and `rhs` are moved in memory, without ever calling `opAssign`, nor any other function. `T` need not be assignable at all to be swapped.

If `lhs` and `rhs` reference the same instance, then nothing is done.

`lhs` and `rhs` must be mutable. If `T` is a struct or union, then its fields must also all be (recursively) mutable.

Parameters:
 T `lhs` Data to be swapped with `rhs`. T `rhs` Data to be swapped with `lhs`.
Examples:
```// Swapping POD (plain old data) types:
int a = 42, b = 34;
swap(a, b);
assert(a == 34 && b == 42);

// Swapping structs with indirection:
static struct S { int x; char c; int[] y; }
S s1 = { 0, 'z', [ 1, 2 ] };
S s2 = { 42, 'a', [ 4, 6 ] };
swap(s1, s2);
writeln(s1.x); // 42
writeln(s1.c); // 'a'
writeln(s1.y); // [4, 6]

writeln(s2.x); // 0
writeln(s2.c); // 'z'
writeln(s2.y); // [1, 2]

// Immutables cannot be swapped:
immutable int imm1 = 1, imm2 = 2;
static assert(!__traits(compiles, swap(imm1, imm2)));

int c = imm1 + 0;
int d = imm2 + 0;
swap(c, d);
writeln(c); // 2
writeln(d); // 1
```
Examples:
```// Non-copyable types can still be swapped.
static struct NoCopy
{
this(this) { assert(0); }
int n;
string s;
}
NoCopy nc1, nc2;
nc1.n = 127; nc1.s = "abc";
nc2.n = 513; nc2.s = "uvwxyz";

swap(nc1, nc2);
assert(nc1.n == 513 && nc1.s == "uvwxyz");
assert(nc2.n == 127 && nc2.s == "abc");

swap(nc1, nc1);
swap(nc2, nc2);
assert(nc1.n == 513 && nc1.s == "uvwxyz");
assert(nc2.n == 127 && nc2.s == "abc");

// Types containing non-copyable fields can also be swapped.
static struct NoCopyHolder
{
NoCopy noCopy;
}
NoCopyHolder h1, h2;
h1.noCopy.n = 31; h1.noCopy.s = "abc";
h2.noCopy.n = 65; h2.noCopy.s = null;

swap(h1, h2);
assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");

swap(h1, h1);
swap(h2, h2);
assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");

// Const types cannot be swapped.
const NoCopy const1, const2;
assert(const1.n == 0 && const2.n == 0);
static assert(!__traits(compiles, swap(const1, const2)));
```
void swapAt(R)(auto ref R r, size_t i1, size_t i2);

Swaps two elements in-place of a range `r`, specified by their indices `i1` and `i2`.

Parameters:
 R `r` a range with swappable elements size_t `i1` first index size_t `i2` second index
Examples:
```import std.algorithm.comparison : equal;
auto a = [1, 2, 3];
a.swapAt(1, 2);
assert(a.equal([1, 3, 2]));
```
Tuple!(InputRange1, InputRange2) swapRanges(InputRange1, InputRange2)(InputRange1 r1, InputRange2 r2)
Constraints: if (hasSwappableElements!InputRange1 && hasSwappableElements!InputRange2 && is(ElementType!InputRange1 == ElementType!InputRange2));

Swaps all elements of `r1` with successive elements in `r2`. Returns a tuple containing the remainder portions of `r1` and `r2` that were not swapped (one of them will be empty). The ranges may be of different types but must have the same element type and support swapping.

Parameters:
 InputRange1 `r1` an input range with swappable elements InputRange2 `r2` an input range with swappable elements
Returns:
Tuple containing the remainder portions of r1 and r2 that were not swapped
Examples:
```import std.range : empty;
int[] a = [ 100, 101, 102, 103 ];
int[] b = [ 0, 1, 2, 3 ];
auto c = swapRanges(a[1 .. 3], b[2 .. 4]);
assert(c.empty && c.empty);
writeln(a); // [100, 2, 3, 103]
writeln(b); // [0, 1, 101, 102]
```
void uninitializedFill(Range, Value)(Range range, Value value)
Constraints: if (isInputRange!Range && hasLvalueElements!Range && is(typeof(range.front = value)));

Initializes each element of `range` with `value`. Assumes that the elements of the range are uninitialized. This is of interest for structs that define copy constructors (for all other types, `fill` and uninitializedFill are equivalent).

Parameters:
 Range `range` An input range that exposes references to its elements and has assignable elements Value `value` Assigned to each element of range
`fill` `initializeAll`
Examples:
```import core.stdc.stdlib : malloc, free;

auto s = (cast(int*) malloc(5 * int.sizeof))[0 .. 5];
uninitializedFill(s, 42);
writeln(s); // [42, 42, 42, 42, 42]

scope(exit) free(s.ptr);
```

© 1999–2019 The D Language Foundation