mirror of
https://github.com/dlang/phobos.git
synced 2025-05-14 17:05:58 +03:00
findSplit, findSplitBefore, findSplitAfter
This commit is contained in:
parent
2fb2876d67
commit
c84f8a6a56
1 changed files with 160 additions and 16 deletions
176
std/algorithm.d
176
std/algorithm.d
|
@ -2989,7 +2989,7 @@ bool findSkip(alias pred = "a == b", R1, R2)(ref R1 haystack, R2 needle)
|
|||
if (isForwardRange!R1 && isForwardRange!R2
|
||||
&& is(typeof(binaryFun!pred(haystack.front, needle.front))))
|
||||
{
|
||||
auto parts = findParts!pred(haystack, needle);
|
||||
auto parts = findSplit!pred(haystack, needle);
|
||||
if (parts[1].empty) return false;
|
||||
// found
|
||||
haystack = parts[2];
|
||||
|
@ -3007,11 +3007,29 @@ unittest
|
|||
}
|
||||
|
||||
/**
|
||||
Given a $(D haystack) and a $(D needle), returns a tuple $(D result)
|
||||
containing three ranges: $(D result[0]) is the portion of $(D
|
||||
haystack) before $(D needle), $(D result[1]) is the portion of $(D
|
||||
haystack) that matches $(D needle), and $(D result[2]) is the portion
|
||||
of $(D haystack) after the match.
|
||||
These functions find the first occurrence of $(D needle) in $(D
|
||||
haystack) and then split $(D haystack) as follows.
|
||||
|
||||
$(D findSplit) returns a tuple $(D result) containing $(I three)
|
||||
ranges. $(D result[0]) is the portion of $(D haystack) before $(D
|
||||
needle), $(D result[1]) is the portion of $(D haystack) that matches
|
||||
$(D needle), and $(D result[2]) is the portion of $(D haystack) after
|
||||
the match.
|
||||
|
||||
$(D findSplitBefore) returns a tuple $(D result) containing two
|
||||
ranges. $(D result[0]) is the portion of $(D haystack) before $(D
|
||||
needle), and $(D result[1]) is the balance of $(D haystack) starting
|
||||
with the match. If $(D needle) was not found, $(D result[0])
|
||||
comprehends $(D haystack) entirely and $(D result[1]) is empty.
|
||||
|
||||
$(D findSplitAfter) returns a tuple $(D result) containing two ranges.
|
||||
$(D result[0]) is the portion of $(D haystack) up to and including the
|
||||
match, and $(D result[1]) is the balance of $(D haystack) starting
|
||||
after the match. If $(D needle) was not found, $(D result[0]) is empty
|
||||
and $(D result[1]) is $(D haystack).
|
||||
|
||||
In all cases, the concatenation of the returned ranges spans the
|
||||
entire $(D haystack).
|
||||
|
||||
If $(D haystack) is a random-access range, all three components of the
|
||||
tuple have the same type as $(D haystack). Otherwise, $(D haystack)
|
||||
|
@ -3021,17 +3039,23 @@ result[1]) is the same as $(XREF range,takeExactly).
|
|||
Example:
|
||||
----
|
||||
auto a = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
|
||||
auto r = findParts(a, [9, 1]);
|
||||
auto r = findSplit(a, [9, 1]);
|
||||
assert(r[0] == a);
|
||||
assert(r[1].empty);
|
||||
assert(r[2].empty);
|
||||
r = findParts(a, [3]);
|
||||
r = findSplit(a, [ 3, 4 ]);
|
||||
assert(r[0] == a[0 .. 2]);
|
||||
assert(r[1] == a[2 .. 3]);
|
||||
assert(r[2] == a[3 .. $]);
|
||||
assert(r[1] == a[2 .. 4]);
|
||||
assert(r[2] == a[4 .. $]);
|
||||
auto r1 = findSplitBefore(a, [ 7, 8 ]);
|
||||
assert(r1[0] == a[0 .. 6]);
|
||||
assert(r1[1] == a[6 .. $]);
|
||||
auto r1 = findSplitAfter(a, [ 7, 8 ]);
|
||||
assert(r1[0] == a);
|
||||
assert(r1[1].empty);
|
||||
----
|
||||
*/
|
||||
auto findParts(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
||||
auto findSplit(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
||||
if (isForwardRange!R1 && isForwardRange!R2)
|
||||
{
|
||||
static if (isSomeString!R1 && isSomeString!R2
|
||||
|
@ -3039,7 +3063,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
{
|
||||
auto balance = find!pred(haystack, needle);
|
||||
immutable pos1 = haystack.length - balance.length;
|
||||
immutable pos2 = balance.length ? pos1 + needle.length : pos1;
|
||||
immutable pos2 = balance.empty ? pos1 : pos1 + needle.length;
|
||||
return tuple(haystack[0 .. pos1],
|
||||
haystack[pos1 .. pos2],
|
||||
haystack[pos2 .. haystack.length]);
|
||||
|
@ -3067,22 +3091,142 @@ if (isForwardRange!R1 && isForwardRange!R2)
|
|||
}
|
||||
}
|
||||
return tuple(takeExactly(original, pos1),
|
||||
takeExactly(haystack, pos2),
|
||||
takeExactly(haystack, pos2 - pos1),
|
||||
h);
|
||||
}
|
||||
}
|
||||
|
||||
/// Ditto
|
||||
auto findSplitBefore(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
||||
if (isForwardRange!R1 && isForwardRange!R2)
|
||||
{
|
||||
static if (isSomeString!R1 && isSomeString!R2
|
||||
|| isRandomAccessRange!R1 && hasLength!R2)
|
||||
{
|
||||
auto balance = find!pred(haystack, needle);
|
||||
immutable pos = haystack.length - balance.length;
|
||||
return tuple(haystack[0 .. pos], haystack[pos .. haystack.length]);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto original = haystack.save;
|
||||
auto h = haystack.save;
|
||||
auto n = needle.save;
|
||||
size_t pos;
|
||||
while (!n.empty && !h.empty)
|
||||
{
|
||||
if (binaryFun!pred(h.front, n.front))
|
||||
{
|
||||
h.popFront();
|
||||
n.popFront();
|
||||
}
|
||||
else
|
||||
{
|
||||
haystack.popFront();
|
||||
n = needle.save;
|
||||
h = haystack.save;
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
return tuple(takeExactly(original, pos), haystack);
|
||||
}
|
||||
}
|
||||
|
||||
/// Ditto
|
||||
auto findSplitAfter(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
|
||||
if (isForwardRange!R1 && isForwardRange!R2)
|
||||
{
|
||||
static if (isSomeString!R1 && isSomeString!R2
|
||||
|| isRandomAccessRange!R1 && hasLength!R2)
|
||||
{
|
||||
auto balance = find!pred(haystack, needle);
|
||||
immutable pos = balance.empty ? 0 : haystack.length - balance.length + needle.length;
|
||||
return tuple(haystack[0 .. pos], haystack[pos .. haystack.length]);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto original = haystack.save;
|
||||
auto h = haystack.save;
|
||||
auto n = needle.save;
|
||||
size_t pos1, pos2;
|
||||
while (!n.empty)
|
||||
{
|
||||
if (h.empty)
|
||||
{
|
||||
// Failed search
|
||||
return tuple(takeExactly(original, 0), original);
|
||||
}
|
||||
if (binaryFun!pred(h.front, n.front))
|
||||
{
|
||||
h.popFront();
|
||||
n.popFront();
|
||||
++pos2;
|
||||
}
|
||||
else
|
||||
{
|
||||
haystack.popFront();
|
||||
n = needle.save;
|
||||
h = haystack.save;
|
||||
pos2 = ++pos1;
|
||||
}
|
||||
}
|
||||
return tuple(takeExactly(original, pos2), h);
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
auto a = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
|
||||
auto r = findParts(a, [9, 1]);
|
||||
assert(equal(r[0], a));
|
||||
auto r = findSplit(a, [9, 1]);
|
||||
assert(r[0] == a);
|
||||
assert(r[1].empty);
|
||||
assert(r[2].empty);
|
||||
r = findParts(a, [3]);
|
||||
r = findSplit(a, [3]);
|
||||
assert(r[0] == a[0 .. 2]);
|
||||
assert(r[1] == a[2 .. 3]);
|
||||
assert(r[2] == a[3 .. $]);
|
||||
|
||||
auto r1 = findSplitBefore(a, [9, 1]);
|
||||
assert(r1[0] == a);
|
||||
assert(r1[1].empty);
|
||||
r1 = findSplitBefore(a, [3, 4]);
|
||||
assert(r1[0] == a[0 .. 2]);
|
||||
assert(r1[1] == a[2 .. $]);
|
||||
|
||||
r1 = findSplitAfter(a, [9, 1]);
|
||||
assert(r1[0].empty);
|
||||
assert(r1[1] == a);
|
||||
r1 = findSplitAfter(a, [3, 4]);
|
||||
assert(r1[0] == a[0 .. 4]);
|
||||
assert(r1[1] == a[4 .. $]);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
auto a = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
|
||||
auto fwd = filter!"a > 0"(a);
|
||||
auto r = findSplit(fwd, [9, 1]);
|
||||
assert(equal(r[0], a));
|
||||
assert(r[1].empty);
|
||||
assert(r[2].empty);
|
||||
r = findSplit(fwd, [3]);
|
||||
assert(equal(r[0], a[0 .. 2]));
|
||||
assert(equal(r[1], a[2 .. 3]));
|
||||
assert(equal(r[2], a[3 .. $]));
|
||||
|
||||
auto r1 = findSplitBefore(fwd, [9, 1]);
|
||||
assert(equal(r1[0], a));
|
||||
assert(r1[1].empty);
|
||||
r1 = findSplitBefore(fwd, [3, 4]);
|
||||
assert(equal(r1[0], a[0 .. 2]));
|
||||
assert(equal(r1[1], a[2 .. $]));
|
||||
|
||||
r1 = findSplitAfter(fwd, [9, 1]);
|
||||
assert(r1[0].empty);
|
||||
assert(equal(r1[1], a));
|
||||
r1 = findSplitAfter(fwd, [3, 4]);
|
||||
assert(equal(r1[0], a[0 .. 4]));
|
||||
assert(equal(r1[1], a[4 .. $]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue