On 7/7/21 5:54 AM, rassoc wrote:
On Wednesday, 7 July 2021 at 01:44:20 UTC, Steven Schveighoffer wrote:
So I have this situation where I need to split a string, then where
the splits are, insert a string to go between the elements making a
new range, all without allocating (hopefully).
Without considering the more general case, isn't that just splitter-joiner?
No, splitter-joiner would make a range of characters, I want a range of
strings.
```d
import std;
auto foo(string s, string sp, string j) @nogc {
return s.splitter(sp).joiner(j);
}
void main() {
foo("ab,cd,ef,gh", ",", "##").writeln; // => ab##cd##ef##gh
}
```
Using your example, the correct result should be `["ab", "##", "cd",
"##", "ef", "##", "gh"]`
Interesting! Tried it myself, shame that this doesn't quite work:
```d
import std;
auto foo(R)(string s, string sp, R r) @nogc {
return s.splitter(sp).zip(r)
.map!(a => a.expand.only)
.joiner.dropBackOne.joiner; // not bidirectional
}
void main() {
foo("ab,cd,ef,gh", ",", ["##", "**"].cycle).writeln;
}
```
ooh, I like the zip/expand/only trick! I got this to work, and lol, I
don't think I'd ever use this:
```d
auto interleave(R, U)(R src, U middles) if (isInputRange!R && is(U ==
ElementType!R))
{
return zip(StoppingPolicy.shortest, src, middles.repeat)
.map!(e => only(e.expand))
.joiner
.slide(2)
.frontTransversal;
}
```
Ironically, I think it would still run the splitting algorithm 2x,
because `slide` has to store 2 copies of the source range. And it's not
nogc either. Hm... I bet `dropBackOne` might actually be able to work on
a forward range if it cached one element? But that might be iffy.
-Steve