mirror of
https://github.com/dlang/phobos.git
synced 2025-05-10 05:41:56 +03:00
Merge pull request #5968 from wilzbach/searching-findSplit
findSplit: return named tuples instead of an anonymous tuple merged-on-behalf-of: Jack Stouffer <jack@jackstouffer.com>
This commit is contained in:
commit
c07b09e214
3 changed files with 84 additions and 40 deletions
23
changelog/std-algorithm-searching-findSplit.dd
Normal file
23
changelog/std-algorithm-searching-findSplit.dd
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
`std.algorithm.searching.findSplit` returns a named tuple
|
||||||
|
|
||||||
|
$(REF findSplit, std,algorithm,searching),
|
||||||
|
$(REF findSplitBefore, std,algorithm,searching), and
|
||||||
|
$(REF findSplitAfter, std,algorithm,searching)
|
||||||
|
will return a named tuple instead of an anonymous tuple:
|
||||||
|
|
||||||
|
---
|
||||||
|
import std.algorithm.searching;
|
||||||
|
auto a = "Carl Sagan Memorial Station";
|
||||||
|
auto r = findSplit(a, " ");
|
||||||
|
assert(r.pre == "Carl");
|
||||||
|
assert(r.match == " ");
|
||||||
|
assert(r.post == "Sagan Memorial Station");
|
||||||
|
|
||||||
|
auto r1 = findSplitBefore(a, "Sagan");
|
||||||
|
assert(r1.pre == "Carl ");
|
||||||
|
assert(r1.post == "Sagan Memorial Station");
|
||||||
|
|
||||||
|
auto r2 = findSplitAfter(a, "Sagan");
|
||||||
|
assert(r2.pre == "Carl Sagan");
|
||||||
|
assert(r2.post == " Memorial Station");
|
||||||
|
---
|
|
@ -2790,30 +2790,32 @@ if (isForwardRange!R1 && ifTestable!(typeof(haystack.front), unaryFun!pred))
|
||||||
These functions find the first occurrence of `needle` in `haystack` and then
|
These functions find the first occurrence of `needle` in `haystack` and then
|
||||||
split `haystack` as follows.
|
split `haystack` as follows.
|
||||||
|
|
||||||
`findSplit` returns a tuple `result` containing $(I three) ranges. `result[0]`
|
`findSplit` returns a `("pre", "separator", "post")` tuple containing three ranges:
|
||||||
is the portion of `haystack` before `needle`, `result[1]` is the portion of
|
$(UL
|
||||||
`haystack` that matches `needle`, and `result[2]` is the portion of `haystack`
|
$(LI `pre` is the portion of `haystack` $(B before) `needle`)
|
||||||
after the match. If `needle` was not found, `result[0]` comprehends `haystack`
|
$(LI `match` is the portion of `haystack` that $(B matches) `needle`)
|
||||||
entirely and `result[1]` and `result[2]` are empty.
|
$(LI `post` is the portion of `haystack` $(B after) the match)
|
||||||
|
)
|
||||||
`findSplitBefore` returns a tuple `result` containing two ranges. `result[0]` is
|
`findSplitBefore` returns a `("pre", "post")` tuple containing two ranges:
|
||||||
the portion of `haystack` before `needle`, and `result[1]` is the balance of
|
$(UL
|
||||||
`haystack` starting with the match. If `needle` was not found, `result[0]`
|
$(LI `pre` is the portion of `haystack` $(B before) `needle`)
|
||||||
comprehends `haystack` entirely and `result[1]` is empty.
|
$(LI `post` is the portion of `haystack` $(B starting) with the found match)
|
||||||
|
)
|
||||||
`findSplitAfter` returns a tuple `result` containing two ranges.
|
`findSplitAfter` returns a `("pre", "post")` tuple containing two ranges:
|
||||||
`result[0]` is the portion of `haystack` up to and including the
|
$(UL
|
||||||
match, and `result[1]` is the balance of `haystack` starting
|
$(LI `pre` is the portion of `haystack` $(B up to and including) the haystack)
|
||||||
after the match. If `needle` was not found, `result[0]` is empty
|
$(LI `post` is the portion of `haystack` $(B after) the found match)
|
||||||
and `result[1]` is `haystack`.
|
)
|
||||||
|
|
||||||
|
If `needle` was not found, `pre` comprehends `haystack` entirely and with
|
||||||
|
`match` and `post` being empty.
|
||||||
In all cases, the concatenation of the returned ranges spans the
|
In all cases, the concatenation of the returned ranges spans the
|
||||||
entire `haystack`.
|
entire `haystack`.
|
||||||
|
|
||||||
If `haystack` is a random-access range, all three components of the tuple have
|
If `haystack` is a random-access range, all three components of the tuple have
|
||||||
the same type as `haystack`. Otherwise, `haystack` must be a
|
the same type as `haystack`. Otherwise, `haystack` must be a
|
||||||
$(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) and
|
$(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) and
|
||||||
the type of `result[0]` and `result[1]` is the same as $(REF takeExactly,
|
the type of `pre` and `match` is the same as $(REF takeExactly,
|
||||||
std,range).
|
std,range).
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
|
@ -2823,8 +2825,9 @@ Params:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
A sub-type of `Tuple!()` of the split portions of `haystack` (see above for
|
A sub-type of `Tuple!("pre", "match", "post")` of the split portions of
|
||||||
details). This sub-type of `Tuple!()` has `opCast` defined for `bool`. This
|
`haystack` (see above for details). This sub-type of $(REF Tuple, std.typecons)
|
||||||
|
has `opCast` defined for `bool`. This
|
||||||
`opCast` returns `true` when the separating `needle` was found
|
`opCast` returns `true` when the separating `needle` was found
|
||||||
(`!result[1].empty`) and `false` otherwise.
|
(`!result[1].empty`) and `false` otherwise.
|
||||||
*/
|
*/
|
||||||
|
@ -2842,7 +2845,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
||||||
{
|
{
|
||||||
asTuple = rhs;
|
asTuple = rhs;
|
||||||
}
|
}
|
||||||
Tuple!(S1, S1, S2) asTuple;
|
Tuple!(S1, "pre", S1, "match", S2, "post") asTuple;
|
||||||
bool opCast(T : bool)()
|
bool opCast(T : bool)()
|
||||||
{
|
{
|
||||||
return !asTuple[1].empty;
|
return !asTuple[1].empty;
|
||||||
|
@ -2906,7 +2909,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
||||||
{
|
{
|
||||||
asTuple = rhs;
|
asTuple = rhs;
|
||||||
}
|
}
|
||||||
Tuple!(S1, S2) asTuple;
|
Tuple!(S1, "pre", S2, "post") asTuple;
|
||||||
bool opCast(T : bool)()
|
bool opCast(T : bool)()
|
||||||
{
|
{
|
||||||
return !asTuple[0].empty;
|
return !asTuple[0].empty;
|
||||||
|
@ -2966,7 +2969,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
||||||
{
|
{
|
||||||
asTuple = rhs;
|
asTuple = rhs;
|
||||||
}
|
}
|
||||||
Tuple!(S1, S2) asTuple;
|
Tuple!(S1, "pre", S2, "post") asTuple;
|
||||||
bool opCast(T : bool)()
|
bool opCast(T : bool)()
|
||||||
{
|
{
|
||||||
return !asTuple[1].empty;
|
return !asTuple[1].empty;
|
||||||
|
@ -3025,7 +3028,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
||||||
{
|
{
|
||||||
// findSplit returns a triplet
|
// findSplit returns a triplet
|
||||||
if (auto split = "dlang-rocks".findSplit("-"))
|
if (auto split = "dlang-rocks".findSplit("-"))
|
||||||
assert(split[2] == "rocks");
|
assert(split.post == "rocks");
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -3035,25 +3038,28 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
||||||
|
|
||||||
auto a = "Carl Sagan Memorial Station";
|
auto a = "Carl Sagan Memorial Station";
|
||||||
auto r = findSplit(a, "Velikovsky");
|
auto r = findSplit(a, "Velikovsky");
|
||||||
import std.typecons : isTuple;
|
|
||||||
static assert(isTuple!(typeof(r.asTuple)));
|
|
||||||
static assert(isTuple!(typeof(r)));
|
|
||||||
assert(!r);
|
assert(!r);
|
||||||
assert(r[0] == a);
|
assert(r.pre == a);
|
||||||
assert(r[1].empty);
|
assert(r.match.empty);
|
||||||
assert(r[2].empty);
|
assert(r.post.empty);
|
||||||
r = findSplit(a, " ");
|
}
|
||||||
assert(r[0] == "Carl");
|
|
||||||
assert(r[1] == " ");
|
///
|
||||||
assert(r[2] == "Sagan Memorial Station");
|
@safe pure nothrow unittest
|
||||||
|
{
|
||||||
|
auto a = "Carl Sagan Memorial Station";
|
||||||
|
auto r = findSplit(a, " ");
|
||||||
|
assert(r.pre == "Carl");
|
||||||
|
assert(r.match == " ");
|
||||||
|
assert(r.post == "Sagan Memorial Station");
|
||||||
|
|
||||||
auto r1 = findSplitBefore(a, "Sagan");
|
auto r1 = findSplitBefore(a, "Sagan");
|
||||||
assert(r1);
|
assert(r1.pre == "Carl ");
|
||||||
assert(r1[0] == "Carl ");
|
assert(r1.post == "Sagan Memorial Station");
|
||||||
assert(r1[1] == "Sagan Memorial Station");
|
|
||||||
auto r2 = findSplitAfter(a, "Sagan");
|
auto r2 = findSplitAfter(a, "Sagan");
|
||||||
assert(r2);
|
assert(r2.pre == "Carl Sagan");
|
||||||
assert(r2[0] == "Carl Sagan");
|
assert(r2.post == " Memorial Station");
|
||||||
assert(r2[1] == " Memorial Station");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use $(REF only, std,range) to find single elements:
|
/// Use $(REF only, std,range) to find single elements:
|
||||||
|
@ -3063,6 +3069,21 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
||||||
assert([1, 2, 3, 4].findSplitBefore(only(3))[0] == [1, 2]);
|
assert([1, 2, 3, 4].findSplitBefore(only(3))[0] == [1, 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@safe pure nothrow unittest
|
||||||
|
{
|
||||||
|
import std.range.primitives : empty;
|
||||||
|
import std.typecons : isTuple;
|
||||||
|
|
||||||
|
auto a = "Carl Sagan Memorial Station";
|
||||||
|
auto r = findSplit(a, "Velikovsky");
|
||||||
|
static assert(isTuple!(typeof(r.asTuple)));
|
||||||
|
static assert(isTuple!(typeof(r)));
|
||||||
|
assert(!r);
|
||||||
|
assert(r.pre == a);
|
||||||
|
assert(r.match.empty);
|
||||||
|
assert(r.post.empty);
|
||||||
|
}
|
||||||
|
|
||||||
@safe pure nothrow unittest
|
@safe pure nothrow unittest
|
||||||
{
|
{
|
||||||
import std.range.primitives : empty;
|
import std.range.primitives : empty;
|
||||||
|
|
|
@ -563,7 +563,7 @@ private template fqnSym(alias T)
|
||||||
|
|
||||||
if (s.skipOver("package ") || s.skipOver("module "))
|
if (s.skipOver("package ") || s.skipOver("module "))
|
||||||
return s;
|
return s;
|
||||||
return s.findSplit("(")[0];
|
return s.findSplit("(").pre;
|
||||||
}
|
}
|
||||||
enum fqnSym = parentPrefix ~ adjustIdent(__traits(identifier, T));
|
enum fqnSym = parentPrefix ~ adjustIdent(__traits(identifier, T));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue