mirror of
https://github.com/dlang/phobos.git
synced 2025-05-01 23:50:31 +03:00
Variadic isSameLength
This commit is contained in:
parent
4ded9c6796
commit
0efda76c67
1 changed files with 75 additions and 27 deletions
|
@ -2031,50 +2031,91 @@ auto predSwitch(alias pred = "a == b", T, R ...)(T switchExpression, lazy R choi
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Checks if the two ranges have the same number of elements. This function is
|
Checks if two or more ranges have the same number of elements. This function is
|
||||||
optimized to always take advantage of the `length` member of either range
|
optimized to always take advantage of the `length` member of either range
|
||||||
if it exists.
|
if it exists.
|
||||||
|
|
||||||
If both ranges have a length member, this function is $(BIGOH 1). Otherwise,
|
If all ranges have a `length` member or at least one is infinite,
|
||||||
this function is $(BIGOH min(r1.length, r2.length)).
|
`_isSameLength`'s complexity is $(BIGOH 1). Otherwise, complexity is
|
||||||
|
$(BIGOH n), where `n` is the smallest of the lengths of ranges with unknown
|
||||||
|
length.
|
||||||
|
|
||||||
Infinite ranges are considered of the same length. An infinite range has never the same length as a
|
Infinite ranges are considered of the same length. An infinite range has never
|
||||||
finite range.
|
the same length as a finite range.
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
r1 = a finite $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
|
rs = two or more $(REF_ALTTEXT input ranges, isInputRange, std,range,primitives)
|
||||||
r2 = a finite $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
`true` if both ranges have the same length, `false` otherwise.
|
`true` if both ranges have the same length, `false` otherwise.
|
||||||
*/
|
*/
|
||||||
bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2)
|
bool isSameLength(Ranges...)(Ranges rs)
|
||||||
if (isInputRange!Range1 && isInputRange!Range2)
|
if (allSatisfy!(isInputRange, Ranges))
|
||||||
{
|
{
|
||||||
static if (isInfinite!Range1 || isInfinite!Range2)
|
static if (anySatisfy!(isInfinite, Ranges))
|
||||||
{
|
{
|
||||||
return isInfinite!Range1 && isInfinite!Range2;
|
return allSatisfy!(isInfinite, Ranges);
|
||||||
}
|
}
|
||||||
else static if (hasLength!(Range1) && hasLength!(Range2))
|
else static if (anySatisfy!(hasLength, Ranges))
|
||||||
{
|
{
|
||||||
return r1.length == r2.length;
|
// Compute the O(1) length
|
||||||
|
auto baselineLength = size_t.max;
|
||||||
|
static foreach (i, R; Ranges)
|
||||||
|
{
|
||||||
|
static if (hasLength!R)
|
||||||
|
{
|
||||||
|
if (baselineLength == size_t.max)
|
||||||
|
baselineLength = rs[i].length;
|
||||||
|
else if (rs[i].length != baselineLength)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else static if (hasLength!(Range1) && !hasLength!(Range2))
|
|
||||||
{
|
|
||||||
return r2.walkLength(r1.length + 1) == r1.length;
|
|
||||||
}
|
}
|
||||||
else static if (!hasLength!(Range1) && hasLength!(Range2))
|
// Iterate all ranges without known length
|
||||||
|
foreach (_; 0 .. baselineLength)
|
||||||
|
static foreach (i, R; Ranges)
|
||||||
{
|
{
|
||||||
return r1.walkLength(r2.length + 1) == r2.length;
|
static if (!hasLength!R)
|
||||||
|
{
|
||||||
|
// All must be non-empty
|
||||||
|
if (rs[i].empty)
|
||||||
|
return false;
|
||||||
|
rs[i].popFront;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static foreach (i, R; Ranges)
|
||||||
|
{
|
||||||
|
static if (!hasLength!R)
|
||||||
|
{
|
||||||
|
// All must be now empty
|
||||||
|
if (!rs[i].empty)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (; !r1.empty; r1.popFront, r2.popFront)
|
// All have unknown length, iterate in lockstep
|
||||||
|
for (;;)
|
||||||
|
static foreach (i, r; rs)
|
||||||
|
{
|
||||||
|
if (r.empty)
|
||||||
|
{
|
||||||
|
// One is empty, so all must be empty
|
||||||
|
static if (i != 0)
|
||||||
{
|
{
|
||||||
if (r2.empty)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return r2.empty;
|
else
|
||||||
|
{
|
||||||
|
static foreach (j, r1; rs[1 .. $])
|
||||||
|
if (!r1.empty)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.popFront;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2139,6 +2180,13 @@ if (isInputRange!Range1 && isInputRange!Range2)
|
||||||
DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Input) r11;
|
DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Input) r11;
|
||||||
auto r12 = new ReferenceInputRange!int([1, 2, 3, 4, 5, 6, 7, 8]);
|
auto r12 = new ReferenceInputRange!int([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||||
assert(!isSameLength(r11, r12));
|
assert(!isSameLength(r11, r12));
|
||||||
|
|
||||||
|
import std.algorithm.iteration : filter;
|
||||||
|
|
||||||
|
assert(isSameLength(filter!"a >= 1"([1, 2, 3]), [4, 5, 6]));
|
||||||
|
assert(!isSameLength(filter!"a > 1"([1, 2, 3]), [4, 5, 6]));
|
||||||
|
|
||||||
|
assert(isSameLength(filter!"a > 1"([1, 2, 3]), filter!"a > 4"([4, 5, 6])));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Still functional but not documented anymore.
|
// Still functional but not documented anymore.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue