mirror of
https://github.com/dlang/phobos.git
synced 2025-05-06 19:16:13 +03:00
add isStrictlySorted for ranges
This commit is contained in:
parent
405858d816
commit
3209fe0bfb
1 changed files with 130 additions and 34 deletions
|
@ -19,6 +19,8 @@ $(T2 isPartitioned,
|
||||||
afterwards.)
|
afterwards.)
|
||||||
$(T2 isSorted,
|
$(T2 isSorted,
|
||||||
$(D isSorted([1, 1, 2, 3])) returns $(D true).)
|
$(D isSorted([1, 1, 2, 3])) returns $(D true).)
|
||||||
|
$(T2 isStrictlySorted,
|
||||||
|
$(D isStrictlySorted([1, 1, 2, 3])) returns $(D false).)
|
||||||
$(T2 ordered,
|
$(T2 ordered,
|
||||||
$(D ordered(1, 1, 2, 3)) returns $(D true).)
|
$(D ordered(1, 1, 2, 3)) returns $(D true).)
|
||||||
$(T2 strictlyOrdered,
|
$(T2 strictlyOrdered,
|
||||||
|
@ -130,53 +132,87 @@ unittest
|
||||||
assert(b == [ 3, 4, 5, 6 ]);
|
assert(b == [ 3, 4, 5, 6 ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool isSortedImpl(alias less = "a < b", bool isStrict = false, Range)(Range r)
|
||||||
|
if (isForwardRange!Range)
|
||||||
|
{
|
||||||
|
if (r.empty) return true;
|
||||||
|
|
||||||
|
static if (isRandomAccessRange!Range && hasLength!Range)
|
||||||
|
{
|
||||||
|
immutable limit = r.length > 0 ? r.length - 1 : 0;
|
||||||
|
foreach (i; 0 .. limit)
|
||||||
|
{
|
||||||
|
static if (isStrict)
|
||||||
|
{
|
||||||
|
if (!binaryFun!less(r[i], r[i + 1])) return false;
|
||||||
|
assert(!binaryFun!less(r[i + 1], r[i]),
|
||||||
|
__FUNCTION__ ~ ": incorrect non-strict predicate.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!binaryFun!less(r[i + 1], r[i])) continue;
|
||||||
|
enum errorMsg = "Predicate for isSorted is not antisymmetric. Both" ~
|
||||||
|
" pred(a, b) and pred(b, a) are true for certain values.";
|
||||||
|
assert(!binaryFun!less(r[i], r[i + 1]), errorMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto ahead = r.save;
|
||||||
|
ahead.popFront();
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (; !ahead.empty; ahead.popFront(), r.popFront(), ++i)
|
||||||
|
{
|
||||||
|
static if (isStrict)
|
||||||
|
{
|
||||||
|
if (!binaryFun!less(r.front, ahead.front)) return false;
|
||||||
|
// Check for antisymmetric predicate
|
||||||
|
enum errorMsg = __FUNCTION__ ~ ": incorrect non-strict predicate.";
|
||||||
|
assert(!binaryFun!less(ahead.front, r.front), errorMsg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!binaryFun!less(ahead.front, r.front)) continue;
|
||||||
|
// Check for antisymmetric predicate
|
||||||
|
enum errorMsg = "Predicate for isSorted is not antisymmetric. Both" ~
|
||||||
|
" pred(a, b) and pred(b, a) are true for certain values.";
|
||||||
|
assert(!binaryFun!less(r.front, ahead.front), errorMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// isSorted
|
// isSorted
|
||||||
/**
|
/**
|
||||||
Checks whether a forward range is sorted according to the comparison
|
Checks whether a forward range is sorted according to the comparison
|
||||||
operation $(D less). Performs $(BIGOH r.length) evaluations of $(D
|
operation $(D less). Performs $(BIGOH r.length) evaluations of $(D
|
||||||
less).
|
less).
|
||||||
|
|
||||||
|
$(D isSorted) allows repeated values, e.g. $(D isSorted([1, 1, 2])) is $(D true). To verify
|
||||||
|
that the values are ordered strictly monotonically, use $(LREF isStrictlySorted):
|
||||||
|
$(D isStrictlySorted([1, 1, 2])) is $(D false).
|
||||||
|
|
||||||
|
With either function, the predicate must be a strict ordering just like with $(D isSorted). For
|
||||||
|
example, using $(D "a <= b") instead of $(D "a < b") is incorrect and will cause failed
|
||||||
|
assertions.
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
less = Predicate the range should be sorted by.
|
less = Predicate the range should be sorted by.
|
||||||
r = Forward range to check for sortedness.
|
r = Forward range to check for sortedness.
|
||||||
|
|
||||||
Returns: true if the range is sorted, false otherwise.
|
Returns: true if the range is sorted, false otherwise.
|
||||||
|
|
||||||
|
See_Also:
|
||||||
|
$(LREF isStrictlySorted) checks whether a forward range is strictly sorted.
|
||||||
*/
|
*/
|
||||||
bool isSorted(alias less = "a < b", Range)(Range r) if (isForwardRange!(Range))
|
bool isSorted(alias less = "a < b", Range)(Range r) if (isForwardRange!Range)
|
||||||
{
|
{
|
||||||
if (r.empty) return true;
|
return isSortedImpl!(less, false)(r);
|
||||||
|
|
||||||
static if (isRandomAccessRange!Range && hasLength!Range)
|
|
||||||
{
|
|
||||||
immutable limit = r.length - 1;
|
|
||||||
foreach (i; 0 .. limit)
|
|
||||||
{
|
|
||||||
if (!binaryFun!less(r[i + 1], r[i])) continue;
|
|
||||||
assert(
|
|
||||||
!binaryFun!less(r[i], r[i + 1]),
|
|
||||||
"Predicate for isSorted is not antisymmetric. Both" ~
|
|
||||||
" pred(a, b) and pred(b, a) are true for certain values.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto ahead = r;
|
|
||||||
ahead.popFront();
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (; !ahead.empty; ahead.popFront(), r.popFront(), ++i)
|
|
||||||
{
|
|
||||||
if (!binaryFun!less(ahead.front, r.front)) continue;
|
|
||||||
// Check for antisymmetric predicate
|
|
||||||
assert(
|
|
||||||
!binaryFun!less(r.front, ahead.front),
|
|
||||||
"Predicate for isSorted is not antisymmetric. Both" ~
|
|
||||||
" pred(a, b) and pred(b, a) are true for certain values.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -205,6 +241,10 @@ bool isSorted(alias less = "a < b", Range)(Range r) if (isForwardRange!(Range))
|
||||||
int[] b = [1, 3, 2];
|
int[] b = [1, 3, 2];
|
||||||
assert(!isSorted(b));
|
assert(!isSorted(b));
|
||||||
|
|
||||||
|
// ignores duplicates
|
||||||
|
int[] c = [1, 1, 2];
|
||||||
|
assert(isSorted(c));
|
||||||
|
|
||||||
dchar[] ds = "コーヒーが好きです"d.dup;
|
dchar[] ds = "コーヒーが好きです"d.dup;
|
||||||
sort(ds);
|
sort(ds);
|
||||||
string s = to!string(ds);
|
string s = to!string(ds);
|
||||||
|
@ -212,6 +252,62 @@ bool isSorted(alias less = "a < b", Range)(Range r) if (isForwardRange!(Range))
|
||||||
assert(isSorted(s)); // bidirectional
|
assert(isSorted(s)); // bidirectional
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isStrictlySorted
|
||||||
|
/**
|
||||||
|
Checks whether a forward range is strictly sorted according to the comparison
|
||||||
|
operation $(D less). Performs $(BIGOH r.length) evaluations of $(D
|
||||||
|
less).
|
||||||
|
|
||||||
|
Params:
|
||||||
|
less = Predicate the range should be strictly sorted by.
|
||||||
|
r = Forward range to check for sortedness.
|
||||||
|
|
||||||
|
Returns: true if the range is strictly sorted, false otherwise.
|
||||||
|
|
||||||
|
See_Also:
|
||||||
|
$(LREF isSorted) checks whether a forward range is sorted without requiring
|
||||||
|
strictness.
|
||||||
|
*/
|
||||||
|
bool isStrictlySorted(alias less = "a < b", Range)(Range r) if (isForwardRange!Range)
|
||||||
|
{
|
||||||
|
return isSortedImpl!(less, true)(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
assert([1, 2].isStrictlySorted);
|
||||||
|
assert(![1, 1, 2].isStrictlySorted);
|
||||||
|
assert([2, 1].isStrictlySorted!((a, b) => a > b));
|
||||||
|
assert(![2, 1, 1].isStrictlySorted!((a, b) => a > b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.conv : to;
|
||||||
|
|
||||||
|
assert("abcd".isStrictlySorted);
|
||||||
|
assert(!"aacd".isStrictlySorted);
|
||||||
|
assert(!"acb".isStrictlySorted);
|
||||||
|
|
||||||
|
assert([1, 2, 3].isStrictlySorted);
|
||||||
|
assert(![1, 3, 2].isStrictlySorted);
|
||||||
|
assert(![1, 1, 2].isStrictlySorted);
|
||||||
|
|
||||||
|
// ー occurs twice -> can't be strict
|
||||||
|
dchar[] ds = "コーヒーが好きです"d.dup;
|
||||||
|
sort(ds);
|
||||||
|
string s = to!string(ds);
|
||||||
|
assert(!isStrictlySorted(ds)); // random-access
|
||||||
|
assert(!isStrictlySorted(s)); // bidirectional
|
||||||
|
|
||||||
|
dchar[] ds2 = "コーヒが好きです"d.dup;
|
||||||
|
sort(ds2);
|
||||||
|
string s2 = to!string(ds2);
|
||||||
|
assert(isStrictlySorted(ds2)); // random-access
|
||||||
|
assert(isStrictlySorted(s2)); // bidirectional
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Like $(D isSorted), returns $(D true) if the given $(D values) are ordered
|
Like $(D isSorted), returns $(D true) if the given $(D values) are ordered
|
||||||
according to the comparison operation $(D less). Unlike $(D isSorted), takes values
|
according to the comparison operation $(D less). Unlike $(D isSorted), takes values
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue