Zip

Iterate several ranges in lockstep. The element type is a proxy tuple that allows accessing the current element in the nth range by using e[n].

zip is similar to lockstep, but lockstep doesn't bundle its elements and uses the opApply protocol. lockstep allows reference access to the elements in foreach iterations.

struct Zip (
Ranges...
) if (
Ranges.length &&
allSatisfy!(isInputRange, Ranges)
) {}

Constructors

this
this(R rs, StoppingPolicy s)

Builds an object. Usually this is invoked indirectly by using the zip function.

Members

Aliases

opDollar
alias opDollar = length

Returns the length of this range. Defined only if all ranges define length.

Functions

moveAt
ElementType moveAt(size_t n)

Destructively reads the nth element in the composite range. Defined if all ranges offer random access.

moveBack
ElementType moveBack()

Moves out the back.

moveFront
ElementType moveFront()

Moves out the front.

opIndex
ElementType opIndex(size_t n)

Returns the nth element in the composite range. Defined if all ranges offer random access.

opIndexAssign
void opIndexAssign(ElementType v, size_t n)

Assigns to the nth element in the composite range. Defined if all ranges offer random access.

opSlice
auto opSlice(size_t from, size_t to)

Returns a slice of the range. Defined only if all range define slicing.

popBack
void popBack()

Calls popBack for all controlled ranges.

popFront
void popFront()

Advances to the next element in all controlled ranges.

Properties

back
ElementType back [@property getter]

Returns the rightmost element.

back
ElementType back [@property setter]

Returns the current iterated element.

empty
bool empty [@property getter]
front
ElementType front [@property getter]

Returns the current iterated element.

front
ElementType front [@property setter]

Sets the front of all iterated ranges.

length
auto length [@property getter]

Returns the length of this range. Defined only if all ranges define length.

save
Zip save [@property getter]

Variables

empty
enum bool empty;

Returns true if the range is at end. The test depends on the stopping policy.

Return Value

At minimum, an input range. Zip offers the lowest range facilities of all components, e.g. it offers random access iff all ranges offer random access, and also offers mutation and swapping if all ranges offer it. Due to this, Zip is extremely powerful because it allows manipulating several ranges in lockstep.

Throws

An Exception if all of the ranges are not the same length and sp is set to StoppingPolicy.requireSameLength.

Limitations: The @nogc and nothrow attributes cannot be inferred for the Zip struct because StoppingPolicy can vary at runtime. This limitation is not shared by the anonymous range returned by the zip function when not given an explicit StoppingPolicy as an argument.

Examples

import std.algorithm.comparison : equal;
import std.algorithm.iteration : map;

// pairwise sum
auto arr = only(0, 1, 2);
auto part1 = zip(arr, arr.dropOne).map!"a[0] + a[1]";
assert(part1.equal(only(1, 3)));
import std.conv : to;

int[] a = [ 1, 2, 3 ];
string[] b = [ "a", "b", "c" ];
string[] result;

foreach (tup; zip(a, b))
{
    result ~= tup[0].to!string ~ tup[1];
}

assert(result == [ "1a", "2b", "3c" ]);

size_t idx = 0;
// unpacking tuple elements with foreach
foreach (e1, e2; zip(a, b))
{
    assert(e1 == a[idx]);
    assert(e2 == b[idx]);
    ++idx;
}

zip is powerful - the following code sorts two arrays in parallel:

import std.algorithm.sorting : sort;

int[] a = [ 1, 2, 3 ];
string[] b = [ "a", "c", "b" ];
zip(a, b).sort!((t1, t2) => t1[0] > t2[0]);

assert(a == [ 3, 2, 1 ]);
// b is sorted according to a's sorting
assert(b == [ "b", "c", "a" ]);

Meta