Bug 10930 – std.array.replace cannot simple replace an element in array
Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-08-30T12:39:26Z
Last change time
2018-11-15T07:20:38Z
Keywords
pull
Assigned to
No Owner
Creator
Temtaime
Comments
Comment #0 by temtaime — 2013-08-30T12:39:26Z
That should be accepted:
auto arr = [ 1, 1, 1 ];
arr = replace(arr, 1, 2);
writeln(arr);
Comment #1 by safety0ff.bugz — 2014-06-13T20:38:14Z
See also: issue #12890
Comment #2 by safety0ff.bugz — 2014-06-13T20:40:06Z
Also, replaceInPlace and replaceSlice are better candidates for this type of operation.
Comment #3 by razvan.nitu1305 — 2017-08-31T09:46:55Z
This should do the trick:
auto arr = [ 1, 1, 1 ];
arr = replace(arr, 1, 2);
writeln(arr);
I suggest we close this.
Comment #4 by razvan.nitu1305 — 2017-08-31T09:47:54Z
This should do the trick:
auto arr = [ 1, 1, 1 ];
replaceInPlace(arr, 1, 2, [2]);
writeln(arr);
I suggest we close this.
Sorry for the above comment. It was a copy-paste mistake.
Comment #5 by petar.p.kirov — 2017-08-31T10:52:15Z
The main issue with `replaceInPlace(arr, 1, 2, [2])` is that:
1. The simple usage requires a dynamic allocation for the `[2]` array. The user could use a separate static array and pass a slice to it, or use `only(2)`, but it's not convenient for such simple use case
2. A `replaceInPlace` overload takes a single element, instead of a range can be made much faster by using specialized SIMD instructions, which is worth considering
Comment #6 by temtaime — 2017-09-01T19:30:12Z
I don't see a reason why single element cannot be replaced
For example, both this examples works:
[1, 2].split([1]);
[1, 2].split(1);
Comment #7 by greensunny12 — 2018-01-09T17:42:14Z
This applied on top of https://github.com/dlang/phobos/pull/6017 will make it work:
diff --git a/std/array.d b/std/array.d
index 3a44612cb..207b1280d 100644
--- a/std/array.d
+++ b/std/array.d
@@ -2120,21 +2120,21 @@ if (isInputRange!RoR &&
$(REF map, std,algorithm,iteration) which can act as a lazy replace
+/
E[] replace(E, R1, R2)(E[] subject, R1 from, R2 to)
-if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2
- && (hasLength!R2 || isSomeString!R2))
+if (isDynamicArray!(E[]))
{
import std.algorithm.searching : find;
import std.range : dropOne;
- if (from.empty) return subject;
+ static if (isInputRange!R1)
+ if (from.empty) return subject;
- auto balance = find(subject, from.save);
+ auto balance = find(subject, from);
if (balance.empty)
return subject;
auto app = appender!(E[])();
app.put(subject[0 .. subject.length - balance.length]);
- app.put(to.save);
+ app.put(to);
// replacing an element in an array is different to a range replacement
static if (is(Unqual!E : Unqual!R1))
replaceInto(app, balance.dropOne, from, to);
@@ -2158,6 +2158,11 @@ if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2
assert([3, 3, 4, 3].replace([3, 3], [1, 1, 1]) == [1, 1, 1, 4, 3]);
}
+@safe unittest
+{
+ assert([0, 1, 2].replace(1, 4) == [0, 4, 2]);
+}
+
// https://issues.dlang.org/show_bug.cgi?id=18215
@safe unittest
{
@@ -2181,28 +2186,29 @@ if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2
/// ditto
void replaceInto(E, Sink, R1, R2)(Sink sink, E[] subject, R1 from, R2 to)
-if (isOutputRange!(Sink, E) && isDynamicArray!(E[])
- && isForwardRange!R1 && isForwardRange!R2
- && (hasLength!R2 || isSomeString!R2))
+if (isOutputRange!(Sink, E) && isDynamicArray!(E[]))
{
import std.algorithm.searching : find;
import std.range : dropOne;
- if (from.empty)
+ static if (isInputRange!R1)
{
- sink.put(subject);
- return;
+ if (from.empty)
+ {
+ sink.put(subject);
+ return;
+ }
}
for (;;)
{
- auto balance = find(subject, from.save);
+ auto balance = find(subject, from);
if (balance.empty)
{
sink.put(subject);
break;
}
sink.put(subject[0 .. subject.length - balance.length]);
- sink.put(to.save);
+ sink.put(to);
// replacing an element in an array is different to a range replacement
static if (is(Unqual!E : Unqual!R1))
subject = balance.dropOne;
Of course constraints need be set, but to be fair currently there aren't any for this