mirror of
https://github.com/dlang/phobos.git
synced 2025-04-30 07:00:37 +03:00
Fix Issue 9702, 10930 - std.array.replace cannot simple replace an element in array
This commit is contained in:
parent
10a969ddaa
commit
bf5dc02f1a
1 changed files with 65 additions and 13 deletions
78
std/array.d
78
std/array.d
|
@ -2336,21 +2336,30 @@ if (isInputRange!RoR &&
|
||||||
$(REF substitute, std,algorithm,iteration) for a lazy replace.
|
$(REF substitute, std,algorithm,iteration) for a lazy replace.
|
||||||
+/
|
+/
|
||||||
E[] replace(E, R1, R2)(E[] subject, R1 from, R2 to)
|
E[] replace(E, R1, R2)(E[] subject, R1 from, R2 to)
|
||||||
if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2
|
if (isDynamicArray!(E[]) &&
|
||||||
&& (hasLength!R2 || isSomeString!R2))
|
((isForwardRange!R1 && isForwardRange!R2 && (hasLength!R2 || isSomeString!R2)) ||
|
||||||
|
is(Unqual!E : Unqual!R1)))
|
||||||
{
|
{
|
||||||
import std.algorithm.searching : find;
|
import std.algorithm.searching : find;
|
||||||
import std.range : dropOne;
|
import std.range : dropOne;
|
||||||
|
|
||||||
if (from.empty) return subject;
|
static if (isInputRange!R1)
|
||||||
|
{
|
||||||
|
if (from.empty) return subject;
|
||||||
|
alias rSave = a => a.save;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias rSave = a => a;
|
||||||
|
}
|
||||||
|
|
||||||
auto balance = find(subject, from.save);
|
auto balance = find(subject, rSave(from));
|
||||||
if (balance.empty)
|
if (balance.empty)
|
||||||
return subject;
|
return subject;
|
||||||
|
|
||||||
auto app = appender!(E[])();
|
auto app = appender!(E[])();
|
||||||
app.put(subject[0 .. subject.length - balance.length]);
|
app.put(subject[0 .. subject.length - balance.length]);
|
||||||
app.put(to.save);
|
app.put(rSave(to));
|
||||||
// replacing an element in an array is different to a range replacement
|
// replacing an element in an array is different to a range replacement
|
||||||
static if (is(Unqual!E : Unqual!R1))
|
static if (is(Unqual!E : Unqual!R1))
|
||||||
replaceInto(app, balance.dropOne, from, to);
|
replaceInto(app, balance.dropOne, from, to);
|
||||||
|
@ -2396,6 +2405,20 @@ if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2
|
||||||
.replace([[0], [1, 2]], [[4]]) == [[4], [0], [3], [1, 2], [4]]);
|
.replace([[0], [1, 2]], [[4]]) == [[4], [0], [3], [1, 2], [4]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://issues.dlang.org/show_bug.cgi?id=10930
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
assert([0, 1, 2].replace(1, 4) == [0, 4, 2]);
|
||||||
|
assert("äbö".replace('ä', 'a') == "abö");
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty array
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
int[] arr;
|
||||||
|
assert(replace(arr, 1, 2) == []);
|
||||||
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Replace occurrences of `from` with `to` in `subject` and output the result into
|
Replace occurrences of `from` with `to` in `subject` and output the result into
|
||||||
`sink`.
|
`sink`.
|
||||||
|
@ -2410,28 +2433,36 @@ if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2
|
||||||
$(REF substitute, std,algorithm,iteration) for a lazy replace.
|
$(REF substitute, std,algorithm,iteration) for a lazy replace.
|
||||||
+/
|
+/
|
||||||
void replaceInto(E, Sink, R1, R2)(Sink sink, E[] subject, R1 from, R2 to)
|
void replaceInto(E, Sink, R1, R2)(Sink sink, E[] subject, R1 from, R2 to)
|
||||||
if (isOutputRange!(Sink, E) && isDynamicArray!(E[])
|
if (isOutputRange!(Sink, E) && isDynamicArray!(E[]) &&
|
||||||
&& isForwardRange!R1 && isForwardRange!R2
|
((isForwardRange!R1 && isForwardRange!R2 && (hasLength!R2 || isSomeString!R2)) ||
|
||||||
&& (hasLength!R2 || isSomeString!R2))
|
is(Unqual!E : Unqual!R1)))
|
||||||
{
|
{
|
||||||
import std.algorithm.searching : find;
|
import std.algorithm.searching : find;
|
||||||
import std.range : dropOne;
|
import std.range : dropOne;
|
||||||
|
|
||||||
if (from.empty)
|
static if (isInputRange!R1)
|
||||||
{
|
{
|
||||||
sink.put(subject);
|
if (from.empty)
|
||||||
return;
|
{
|
||||||
|
sink.put(subject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
alias rSave = a => a.save;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias rSave = a => a;
|
||||||
}
|
}
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
auto balance = find(subject, from.save);
|
auto balance = find(subject, rSave(from));
|
||||||
if (balance.empty)
|
if (balance.empty)
|
||||||
{
|
{
|
||||||
sink.put(subject);
|
sink.put(subject);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sink.put(subject[0 .. subject.length - balance.length]);
|
sink.put(subject[0 .. subject.length - balance.length]);
|
||||||
sink.put(to.save);
|
sink.put(rSave(to));
|
||||||
// replacing an element in an array is different to a range replacement
|
// replacing an element in an array is different to a range replacement
|
||||||
static if (is(Unqual!E : Unqual!R1))
|
static if (is(Unqual!E : Unqual!R1))
|
||||||
subject = balance.dropOne;
|
subject = balance.dropOne;
|
||||||
|
@ -2453,6 +2484,15 @@ if (isOutputRange!(Sink, E) && isDynamicArray!(E[])
|
||||||
assert(sink.data == [1, 4, 6, 4, 5]);
|
assert(sink.data == [1, 4, 6, 4, 5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// empty array
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
auto sink = appender!(int[])();
|
||||||
|
int[] arr;
|
||||||
|
replaceInto(sink, arr, 1, 2);
|
||||||
|
assert(sink.data == []);
|
||||||
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
import std.algorithm.comparison : cmp;
|
import std.algorithm.comparison : cmp;
|
||||||
|
@ -2506,6 +2546,18 @@ if (isOutputRange!(Sink, E) && isDynamicArray!(E[])
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://issues.dlang.org/show_bug.cgi?id=10930
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
auto sink = appender!(int[])();
|
||||||
|
replaceInto(sink, [0, 1, 2], 1, 5);
|
||||||
|
assert(sink.data == [0, 5, 2]);
|
||||||
|
|
||||||
|
auto sink2 = appender!(dchar[])();
|
||||||
|
replaceInto(sink2, "äbö", 'ä', 'a');
|
||||||
|
assert(sink2.data == "abö");
|
||||||
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Replaces elements from `array` with indices ranging from `from`
|
Replaces elements from `array` with indices ranging from `from`
|
||||||
(inclusive) to `to` (exclusive) with the range `stuff`.
|
(inclusive) to `to` (exclusive) with the range `stuff`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue