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

Reply via email to