mirror of
https://github.com/dlang/phobos.git
synced 2025-04-29 14:40:30 +03:00
Merge pull request #4921 from RazvanN7/Issue_8573
Issue 8573 - A simpler Phobos function that returns the index of the …
This commit is contained in:
commit
f3a840144a
1 changed files with 207 additions and 0 deletions
|
@ -3544,6 +3544,213 @@ unittest
|
|||
assert(minPos!("a[0] < b[0]")(b) == [ [2, 4], [4], [4] ]);
|
||||
}
|
||||
|
||||
/**
|
||||
Computes the index of the first occurrence of `range`'s minimum element.
|
||||
|
||||
Params:
|
||||
pred = The ordering predicate to use to determine the minimum element.
|
||||
range = The input range to search.
|
||||
|
||||
Complexity: O(n)
|
||||
Exactly `n - 1` comparisons are needed.
|
||||
|
||||
Returns:
|
||||
The index of the first encounter of the minimum element in `range`. If the
|
||||
`range` is empty, -1 is returned.
|
||||
|
||||
See_Also:
|
||||
$(REF min, std,algorithm,comparison), $(LREF minCount), $(LREF minElement), $(LREF minPos)
|
||||
*/
|
||||
sizediff_t minIndex(alias pred = "a < b", Range)(Range range)
|
||||
if (isForwardRange!Range && !isInfinite!Range &&
|
||||
is(typeof(binaryFun!pred(range.front, range.front))))
|
||||
{
|
||||
if (range.empty) return -1;
|
||||
|
||||
sizediff_t minPos = 0;
|
||||
|
||||
static if (isRandomAccessRange!Range && hasLength!Range)
|
||||
{
|
||||
foreach (i; 1 .. range.length)
|
||||
{
|
||||
if (binaryFun!pred(range[i], range[minPos]))
|
||||
{
|
||||
minPos = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sizediff_t curPos = 0;
|
||||
Unqual!(typeof(range.front)) min = range.front;
|
||||
for (range.popFront(); !range.empty; range.popFront())
|
||||
{
|
||||
++curPos;
|
||||
if (binaryFun!pred(range.front, min))
|
||||
{
|
||||
min = range.front;
|
||||
minPos = curPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
return minPos;
|
||||
}
|
||||
|
||||
///
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
int[] a = [2, 3, 4, 1, 2, 4, 1, 1, 2];
|
||||
|
||||
// Minimum is 1 and first occurs in position 3
|
||||
assert(a.minIndex == 3);
|
||||
// Get maximum index with minIndex
|
||||
assert(a.minIndex!"a > b" == 2);
|
||||
|
||||
// Range is empty, so return value is -1
|
||||
int[] b;
|
||||
assert(b.minIndex == -1);
|
||||
|
||||
// Works with more custom types
|
||||
struct Dog { int age; }
|
||||
Dog[] dogs = [Dog(10), Dog(5), Dog(15)];
|
||||
assert(dogs.minIndex!"a.age < b.age" == 1);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
// should work with const
|
||||
const(int)[] immArr = [2, 1, 3];
|
||||
assert(immArr.minIndex == 1);
|
||||
|
||||
// Works for const ranges too
|
||||
const int[] c = [2, 5, 4, 1, 2, 3];
|
||||
assert(c.minIndex == 3);
|
||||
|
||||
// should work with immutable
|
||||
immutable(int)[] immArr2 = [2, 1, 3];
|
||||
assert(immArr2.minIndex == 1);
|
||||
|
||||
// with strings
|
||||
assert(["b", "a", "c"].minIndex == 1);
|
||||
|
||||
// infinite range
|
||||
import std.range : cycle;
|
||||
static assert(!__traits(compiles, cycle([1]).minIndex));
|
||||
|
||||
// with all dummy ranges
|
||||
import std.internal.test.dummyrange : AllDummyRanges;
|
||||
foreach (DummyType; AllDummyRanges)
|
||||
{
|
||||
static if (isForwardRange!DummyType && !isInfinite!DummyType)
|
||||
{
|
||||
DummyType d;
|
||||
d.arr = [5, 3, 7, 2, 1, 4];
|
||||
assert(d.minIndex == 4);
|
||||
|
||||
d.arr = [];
|
||||
assert(d.minIndex == -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@nogc @safe nothrow pure unittest
|
||||
{
|
||||
static immutable arr = [7, 3, 8, 2, 1, 4];
|
||||
assert(arr.minIndex == 4);
|
||||
|
||||
static immutable arr2d = [[1, 3], [3, 9], [4, 2]];
|
||||
assert(arr2d.minIndex!"a[1] < b[1]" == 2);
|
||||
}
|
||||
|
||||
/**
|
||||
Computes the index of the first occurrence of `range`'s maximum element.
|
||||
|
||||
Complexity: O(n)
|
||||
Exactly `n - 1` comparisons are needed.
|
||||
|
||||
Params:
|
||||
pred = The ordering predicate to use to determine the maximum element.
|
||||
range = The input range to search.
|
||||
|
||||
Returns:
|
||||
The index of the first encounter of the maximum in `range`. If the
|
||||
`range` is empty, -1 is returned.
|
||||
|
||||
See_Also:
|
||||
$(REF max, std,algorithm,comparison), $(LREF maxCount), $(LREF maxElement), $(LREF maxPos)
|
||||
*/
|
||||
sizediff_t maxIndex(alias pred = "a < b", Range)(Range range)
|
||||
if (isInputRange!Range && !isInfinite!Range &&
|
||||
is(typeof(binaryFun!pred(range.front, range.front))))
|
||||
{
|
||||
return range.minIndex!((a, b) => binaryFun!pred(b, a));
|
||||
}
|
||||
|
||||
///
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
// Maximum is 4 and first occurs in position 2
|
||||
int[] a = [2, 3, 4, 1, 2, 4, 1, 1, 2];
|
||||
assert(a.maxIndex == 2);
|
||||
|
||||
// Empty range
|
||||
int[] b;
|
||||
assert(b.maxIndex == -1);
|
||||
|
||||
// Works with more custom types
|
||||
struct Dog { int age; }
|
||||
Dog[] dogs = [Dog(10), Dog(15), Dog(5)];
|
||||
assert(dogs.maxIndex!"a.age < b.age" == 1);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
// should work with const
|
||||
const(int)[] immArr = [5, 1, 3];
|
||||
assert(immArr.maxIndex == 0);
|
||||
|
||||
// Works for const ranges too
|
||||
const int[] c = [2, 5, 4, 1, 2, 3];
|
||||
assert(c.maxIndex == 1);
|
||||
|
||||
|
||||
// should work with immutable
|
||||
immutable(int)[] immArr2 = [2, 1, 3];
|
||||
assert(immArr2.maxIndex == 2);
|
||||
|
||||
// with strings
|
||||
assert(["b", "a", "c"].maxIndex == 2);
|
||||
|
||||
// infinite range
|
||||
import std.range : cycle;
|
||||
static assert(!__traits(compiles, cycle([1]).maxIndex));
|
||||
|
||||
// with all dummy ranges
|
||||
import std.internal.test.dummyrange : AllDummyRanges;
|
||||
foreach (DummyType; AllDummyRanges)
|
||||
{
|
||||
static if (isForwardRange!DummyType && !isInfinite!DummyType)
|
||||
{
|
||||
DummyType d;
|
||||
|
||||
d.arr = [5, 3, 7, 2, 1, 4];
|
||||
assert(d.maxIndex == 2);
|
||||
|
||||
d.arr = [];
|
||||
assert(d.maxIndex == -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@nogc @safe nothrow pure unittest
|
||||
{
|
||||
static immutable arr = [7, 3, 8, 2, 1, 4];
|
||||
assert(arr.maxIndex == 2);
|
||||
|
||||
static immutable arr2d = [[1, 3], [3, 9], [4, 2]];
|
||||
assert(arr2d.maxIndex!"a[1] < b[1]" == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
Skip over the initial portion of the first given range that matches the second
|
||||
range, or do nothing if there is no match.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue