mirror of
https://github.com/dlang/phobos.git
synced 2025-05-12 15:17:12 +03:00
issue 5224
This commit is contained in:
parent
82b4f1c901
commit
98b47ad5dd
1 changed files with 58 additions and 93 deletions
145
std/algorithm.d
145
std/algorithm.d
|
@ -7217,120 +7217,72 @@ cases.))
|
|||
Range remove
|
||||
(SwapStrategy s = SwapStrategy.stable, Range, Offset...)
|
||||
(Range range, Offset offset)
|
||||
if (isBidirectionalRange!Range && hasLength!Range && s != SwapStrategy.stable
|
||||
if (s != SwapStrategy.stable
|
||||
&& isBidirectionalRange!Range && hasLength!Range
|
||||
&& Offset.length >= 1)
|
||||
{
|
||||
enum bool tupleLeft = is(typeof(offset[0][0]))
|
||||
&& is(typeof(offset[0][1]));
|
||||
enum bool tupleRight = is(typeof(offset[$ - 1][0]))
|
||||
&& is(typeof(offset[$ - 1][1]));
|
||||
static if (!tupleLeft)
|
||||
Tuple!(size_t, size_t)[offset.length] blackouts;
|
||||
foreach (i, v; offset)
|
||||
{
|
||||
alias offset[0] lStart;
|
||||
auto lEnd = lStart + 1;
|
||||
static if (is(typeof(v[0]) : size_t) && is(typeof(v[1]) : size_t))
|
||||
{
|
||||
blackouts[i][0] = v[0];
|
||||
blackouts[i][1] = v[1] - v[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
auto lStart = offset[0][0];
|
||||
auto lEnd = offset[0][1];
|
||||
}
|
||||
static if (!tupleRight)
|
||||
{
|
||||
alias offset[$ - 1] rStart;
|
||||
auto rEnd = rStart + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto rStart = offset[$ - 1][0];
|
||||
auto rEnd = offset[$ - 1][1];
|
||||
}
|
||||
// Begin. Test first to see if we need to remove the rightmost
|
||||
// element(s) in the range. In that case, life is simple - chop
|
||||
// and recurse.
|
||||
if (rEnd == range.length)
|
||||
{
|
||||
// must remove the last elements of the range
|
||||
range.popBackN(rEnd - rStart);
|
||||
static if (Offset.length > 1)
|
||||
{
|
||||
return .remove!(s, Range, Offset[0 .. $ - 1])
|
||||
(range, offset[0 .. $ - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return range;
|
||||
static assert(is(typeof(v) : size_t), typeof(v).stringof);
|
||||
blackouts[i][0] = v;
|
||||
blackouts[i][1] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Ok, there are "live" elements at the end of the range
|
||||
auto t = range;
|
||||
auto lDelta = lEnd - lStart, rDelta = rEnd - rStart;
|
||||
auto rid = min(lDelta, rDelta);
|
||||
foreach (i; 0 .. rid)
|
||||
size_t left = 0, right = offset.length - 1;
|
||||
auto tgt = range.save;
|
||||
size_t steps = 0;
|
||||
|
||||
while (left <= right)
|
||||
{
|
||||
move(range.back, t.front);
|
||||
// Look for a blackout on the right
|
||||
if (blackouts[right][0] + blackouts[right][1] >= range.length)
|
||||
{
|
||||
range.popBackN(blackouts[right][1]);
|
||||
--right;
|
||||
continue;
|
||||
}
|
||||
// Advance to next blackout on the left
|
||||
assert(blackouts[left][0] >= steps);
|
||||
tgt.popFrontN(blackouts[left][0] - steps);
|
||||
steps = blackouts[left][0];
|
||||
auto toMove = min(blackouts[left][1], blackouts[right][1]);
|
||||
foreach (i; 0 .. toMove)
|
||||
{
|
||||
move(range.back, tgt.front);
|
||||
range.popBack();
|
||||
t.popFront();
|
||||
tgt.popFront();
|
||||
}
|
||||
if (rEnd - rStart == lEnd - lStart)
|
||||
steps += toMove;
|
||||
if (toMove == blackouts[left][1])
|
||||
{
|
||||
// We got rid of both left and right
|
||||
static if (Offset.length > 2)
|
||||
{
|
||||
return .remove!(s, Range, Offset[1 .. $ - 1])
|
||||
(range, offset[1 .. $ - 1]);
|
||||
// Filled the entire left hole
|
||||
++left;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
return range;
|
||||
}
|
||||
}
|
||||
else if (rEnd - rStart < lEnd - lStart)
|
||||
{
|
||||
// We got rid of the entire right subrange
|
||||
static if (Offset.length > 2)
|
||||
{
|
||||
return .remove!(s, Range)
|
||||
(range, tuple(lStart + rid, lEnd),
|
||||
offset[1 .. $ - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = tuple(lStart + rid, lEnd);
|
||||
return .remove!(s, Range, typeof(tmp))
|
||||
(range, tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We got rid of the entire left subrange
|
||||
static if (Offset.length > 2)
|
||||
{
|
||||
return .remove!(s, Range)
|
||||
(range, offset[1 .. $ - 1],
|
||||
tuple(rStart, lEnd - rid));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = tuple(rStart, lEnd - rid);
|
||||
return .remove!(s, Range, typeof(tmp))
|
||||
(range, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ditto
|
||||
Range remove
|
||||
(SwapStrategy s = SwapStrategy.stable, Range, Offset...)
|
||||
(Range range, Offset offset)
|
||||
if ((isForwardRange!Range && !isBidirectionalRange!Range
|
||||
|| !hasLength!Range || s == SwapStrategy.stable)
|
||||
&& Offset.length >= 1)
|
||||
if (s == SwapStrategy.stable && isForwardRange!Range && Offset.length >= 1)
|
||||
{
|
||||
auto result = range;
|
||||
auto src = range, tgt = range;
|
||||
size_t pos;
|
||||
foreach (i; offset)
|
||||
foreach (pass, i; offset)
|
||||
{
|
||||
static if (is(typeof(i[0])) && is(typeof(i[1])))
|
||||
{
|
||||
|
@ -7342,10 +7294,19 @@ if ((isForwardRange!Range && !isBidirectionalRange!Range
|
|||
enum delta = 1;
|
||||
}
|
||||
assert(pos <= from);
|
||||
if (pass > 0)
|
||||
{
|
||||
for (; pos < from; ++pos, src.popFront(), tgt.popFront())
|
||||
{
|
||||
move(src.front, tgt.front);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
src.popFrontN(from);
|
||||
tgt.popFrontN(from);
|
||||
pos = from;
|
||||
}
|
||||
// now skip source to the "to" position
|
||||
src.popFrontN(delta);
|
||||
pos += delta;
|
||||
|
@ -7373,6 +7334,10 @@ unittest
|
|||
a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
|
||||
assert(remove!(SwapStrategy.unstable)(a, 0, tuple(9, 11)) ==
|
||||
[ 8, 1, 2, 3, 4, 5, 6, 7 ]);
|
||||
// http://d.puremagic.com/issues/show_bug.cgi?id=5224
|
||||
a = [ 1, 2, 3, 4 ];
|
||||
assert(remove!(SwapStrategy.unstable)(a, 2) ==
|
||||
[ 1, 2, 4 ]);
|
||||
|
||||
a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
|
||||
//writeln(remove!(SwapStrategy.stable)(a, 1, 5));
|
||||
|
@ -7415,7 +7380,7 @@ if (isBidirectionalRange!Range)
|
|||
{
|
||||
for (;!range.empty;)
|
||||
{
|
||||
if (!unaryFun!(pred)(range.front))
|
||||
if (!unaryFun!pred(range.front))
|
||||
{
|
||||
range.popFront();
|
||||
continue;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue