Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Forums
  - IRC
  - Wiki
  - GitHub
  - Issues
  - Foundation
  - Donate
- Resources
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

# 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[5], 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[3], 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.
moveAll | Moves all elements from one range to another.
moveSome | Moves as many elements as possible from one range to another.
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 [0].
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.

License:
Boost License 1.0.
Authors:
Andrei Alexandrescu

Source: std/algorithm/mutation.d

size_t `bringToFront`(InputRange, ForwardRange)(InputRange `front`, ForwardRange `back`)
if (isInputRange!InputRange && isForwardRange!ForwardRange);
  The `bringToFront` function has considerable flexibility and usefulness. It 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.
  `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.

  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`.
  See Also:
  STL's rotate
TargetRange `copy`(SourceRange, TargetRange)(SourceRange `source`, TargetRange `target`)
if (areCopyCompatibleArrays!(SourceRange, TargetRange));
TargetRange `copy`(SourceRange, TargetRange)(SourceRange `source`, TargetRange `target`)
if (!areCopyCompatibleArrays!(SourceRange, TargetRange) && 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`
  See Also:
  STL's copy
  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
      assert(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);
      assert(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);
      assert(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);
      assert(dest == [0, 0, 1, 2, 4]);

void `fill`(Range, Value)(Range `range`, Value `value`)
if (isInputRange!Range && is(typeof(`range`.front = `value`)));
  Assigns `value` to each element of input range `range`.
  Parameters:

  Range `range` | An input range that exposes references to its elements and has assignable elements
  Value `value` | Assigned to each element of `range`

  See Also:
  uninitializedFill initializeAll
  Examples:

      int[] a = [ 1, 2, 3, 4 ];
      fill(a, 5);
      assert(a == [ 5, 5, 5, 5 ]);

void `fill`(InputRange, ForwardRange)(InputRange `range`, ForwardRange `filler`)
if (isInputRange!InputRange && (isForwardRange!ForwardRange || isInputRange!ForwardRange && isInfinite!ForwardRange) && is(typeof(InputRange.init.front = ForwardRange.init.front)));
  Fills `range` with a pattern copied from `filler`. The length of `range` does not have to be a multiple of the length of `filler`. If `filler` is empty, an exception is thrown.
  Parameters:

  InputRange `range` | An input range that exposes references to its elements and has assignable elements.
  ForwardRange `filler` | The forward range representing the fill pattern.

  Examples:

      int[] a = [ 1, 2, 3, 4, 5 ];
      int[] b = [ 8, 9 ];
      fill(a, b);
      assert(a == [ 8, 9, 8, 9, 8 ]);

void `initializeAll`(Range)(Range `range`)
if (isInputRange!Range && hasLvalueElements!Range && hasAssignableElements!Range);
void `initializeAll`(Range)(Range `range`)
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

  See Also:
  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);
      assert(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)(ref 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, 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);

      assert(s12 == S1(10, 11));
      assert(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);

      assert(s21 == S2(1, 2));
      assert(s22 == S2(3, 4));

  Examples:
  Non-copyable structs can still be moved:

      struct S
      {
          @disable this(this);
          ~this() pure nothrow @safe @nogc {}
      }
      S s1;
      S s2 = move(s1);

@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);
      assert(val == 0);

InputRange2 `moveAll`(InputRange1, InputRange2)(InputRange1 `src`, InputRange2 `tgt`)
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[3] a = [ 1, 2, 3 ];
      int[5] b;
      assert(moveAll(a[], b[]) is b[3 .. $]);
      assert(a[] == b[0 .. 3]);
      int[3] cmp = [ 1, 2, 3 ];
      assert(a[] == cmp[]);

@system InputRange2 `moveEmplaceAll`(InputRange1, InputRange2)(InputRange1 `src`, InputRange2 `tgt`)
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[3] refs = [0, 1, 2];
      Foo[3] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2])];
      Foo[5] 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`)
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[5] a = [ 1, 2, 3, 4, 5 ];
      int[3] b;
      assert(moveSome(a[], b[])[0] is a[3 .. $]);
      assert(a[0 .. 3] == b);
      assert(a == [ 1, 2, 3, 4, 5 ]);

@system Tuple!(InputRange1, InputRange2) `moveEmplaceSome`(InputRange1, InputRange2)(InputRange1 `src`, InputRange2 `tgt`)
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[4] refs = [0, 1, 2, 3];
      Foo[4] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2]), Foo(&refs[3])];
      Foo[3] dst = void;

      auto res = moveEmplaceSome(src[], dst[]);

      import std.algorithm.searching : all;
      assert(src[0 .. 3].all!(e => e._ptr is null));
      assert(src[3]._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.
  `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`)
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);
  Eliminates elements at given offsets from `range` and returns the shortened `range`. In the simplest call, one element is removed.

      int[] a = [ 3, 5, 7, 8 ];
      assert(remove(a, 1) == [ 3, 7, 8 ]);
      assert(a == [ 3, 7, 8, 8 ]);

  In the case above the element at `offset` 1 is removed and `remove` returns the `range` smaller by one element. The original array has remained of the same length because all functions in std.algorithm only change content, not topology. The value 8 is repeated because move was invoked to move elements around and on integers move simply copies the source to the destination. To replace a with the effect of the removal, simply assign a = `remove`(a, 1). The slice will be rebound to the shorter array and the operation completes with maximal efficiency.
  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 how 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.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
  Examples:

      import std.typecons : tuple;

      auto a = [ 0, 1, 2, 3, 4, 5 ];
      assert(remove!(SwapStrategy.stable)(a, 1) == [ 0, 2, 3, 4, 5 ]);
      a = [ 0, 1, 2, 3, 4, 5 ];
      assert(remove!(SwapStrategy.stable)(a, 1, 3) == [ 0, 2, 4, 5] );
      a = [ 0, 1, 2, 3, 4, 5 ];
      assert(remove!(SwapStrategy.stable)(a, 1, tuple(3, 6)) == [ 0, 2 ]);

      a = [ 0, 1, 2, 3, 4, 5 ];
      assert(remove!(SwapStrategy.unstable)(a, 1) == [0, 5, 2, 3, 4]);
      a = [ 0, 1, 2, 3, 4, 5 ];
      assert(remove!(SwapStrategy.unstable)(a, tuple(1, 4)) == [0, 5, 4]);

Range `remove`(alias pred, SwapStrategy s = SwapStrategy.stable, Range)(Range `range`)
if (isBidirectionalRange!Range && hasLvalueElements!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

  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
      assert(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
      assert(remove!(a => a == 2)(arr) == [ 1, 3, 4, 5 ]);

void `reverse`(Range)(Range `r`)
if (isBidirectionalRange!Range && !isRandomAccessRange!Range && hasSwappableElements!Range);
void `reverse`(Range)(Range `r`)
if (isRandomAccessRange!Range && hasLength!Range);
  Reverses `r` in-place. Performs `r`.length / 2 evaluations of swap.
  Parameters:

  Range `r` | a bidirectional range with swappable elements or a random access range with a length member

  See Also:
  STL's reverse
  Examples:

      int[] arr = [ 1, 2, 3 ];
      reverse(arr);
      assert(arr == [ 3, 2, 1 ]);

void `reverse`(Char)(Char[] `s`)
if (isNarrowString!(Char[]) && !is(Char == const) && !is(Char == immutable));
  Reverses r in-place, where r is a narrow string (having elements of type char or wchar). UTF sequences consisting of multiple code units are preserved properly.
  Parameters:

  Char[] `s` | a narrow string

  Bugs:
  When passing a sting 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").
  Examples:

      char[] arr = "hello\U00010143\u0100\U00010143".dup;
      reverse(arr);
      assert(arr == "\U00010143\u0100\U00010143olleh");

Range `strip`(Range, E)(Range `range`, E `element`)
if (isBidirectionalRange!Range && is(typeof(`range`.front == `element`) : bool));
Range `strip`(alias pred, Range)(Range `range`)
if (isBidirectionalRange!Range && is(typeof(pred(`range`.back)) : bool));
Range `stripLeft`(Range, E)(Range `range`, E `element`)
if (isInputRange!Range && is(typeof(`range`.front == `element`) : bool));
Range `stripLeft`(alias pred, Range)(Range `range`)
if (isInputRange!Range && is(typeof(pred(`range`.front)) : bool));
Range `stripRight`(Range, E)(Range `range`, E `element`)
if (isBidirectionalRange!Range && is(typeof(`range`.back == `element`) : bool));
Range `stripRight`(alias pred, Range)(Range `range`)
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 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`.

      assert("  foobar  ".strip(' ') == "foobar");
      assert("00223.444500".strip('0') == "223.4445");
      assert("ëëêéüŗōpéêëë".strip('ë') == "êéüŗōpéê");
      assert([1, 1, 0, 1, 1].strip(1) == [0]);
      assert([0.0, 0.01, 0.01, 0.0].strip(0).length == 2);

  Examples:
  Strip leading and trailing elements while the predicate returns `true`.

      assert("  foobar  ".strip!(a => a == ' ')() == "foobar");
      assert("00223.444500".strip!(a => a == '0')() == "223.4445");
      assert("ëëêéüŗōpéêëë".strip!(a => a == 'ë')() == "êéüŗōpéê");
      assert([1, 1, 0, 1, 1].strip!(a => a == 1)() == [0]);
      assert([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`.

      assert("  foobar  ".stripLeft(' ') == "foobar  ");
      assert("00223.444500".stripLeft('0') == "223.444500");
      assert("ůůűniçodêéé".stripLeft('ů') == "űniçodêéé");
      assert([1, 1, 0, 1, 1].stripLeft(1) == [0, 1, 1]);
      assert([0.0, 0.01, 0.01, 0.0].stripLeft(0).length == 3);

  Examples:
  Strip leading elements while the predicate returns `true`.

      assert("  foobar  ".stripLeft!(a => a == ' ')() == "foobar  ");
      assert("00223.444500".stripLeft!(a => a == '0')() == "223.444500");
      assert("ůůűniçodêéé".stripLeft!(a => a == 'ů')() == "űniçodêéé");
      assert([1, 1, 0, 1, 1].stripLeft!(a => a == 1)() == [0, 1, 1]);
      assert([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`.

      assert("  foobar  ".stripRight(' ') == "  foobar");
      assert("00223.444500".stripRight('0') == "00223.4445");
      assert("ùniçodêéé".stripRight('é') == "ùniçodê");
      assert([1, 1, 0, 1, 1].stripRight(1) == [1, 1, 0]);
      assert([0.0, 0.01, 0.01, 0.0].stripRight(0).length == 3);

  Examples:
  Strip trailing elements while the predicate returns `true`.

      assert("  foobar  ".stripRight!(a => a == ' ')() == "  foobar");
      assert("00223.444500".stripRight!(a => a == '0')() == "00223.4445");
      assert("ùniçodêéé".stripRight!(a => a == 'é')() == "ùniçodê");
      assert([1, 1, 0, 1, 1].stripRight!(a => a == 1)() == [1, 1, 0]);
      assert([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`)
if (isBlitAssignable!T && !is(typeof(`lhs`.proxySwap(`rhs`))));
void `swap`(T)(ref T `lhs`, ref T `rhs`)
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);
      assert(s1.x == 42);
      assert(s1.c == 'a');
      assert(s1.y == [ 4, 6 ]);

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

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

  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;
      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`)
if (isInputRange!InputRange1 && isInputRange!InputRange2 && 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[0].empty && c[1].empty);
      assert(a == [ 100, 2, 3, 103 ]);
      assert(b == [ 0, 1, 101, 102 ]);

void `uninitializedFill`(Range, Value)(Range `range`, Value `value`)
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`

  See Also:
  fill initializeAll
  Examples:

      import core.stdc.stdlib : malloc, free;

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

      scope(exit) free(s.ptr);

Andrei Alexandrescu 2008-. | Page generated by Ddoc on Sun Jan 22 15:47:33 2017