www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is there a smart way to process a range of range by front ?

reply BBasile <bb.temp gmx.com> writes:
I was thinking to a general *interleave()* algorithm for any 
compatible Range of Range but I can't find any smart way to 
process each sub range by front, eg:

---
void interleave(RoR)(RoR r)
{
    r.each!(a => a.writeln);
}

void main()
{
     auto r = [[0,2],[1,3]];
     interleave(r);
}
---

will print:
[0,2]
[1,3]

while to interleave i need to take the front of each sub range 
before poping each ror element.

Currently I'm here (don't run this ;)) :

---
auto interleave(RoR)(RoR r)
{
     alias T = ElementType!r[0];
     T[] result;
     while (!empty(r[0]))
         r.each!(a => (result ~= a.front, a.popFront));
     return result;
}

void main()
{
     auto r = [[0,2],[1,3]];
     interleave(r);
}
---

but it doesn't work because 'a' is not consumed. It looks like 
it's saved from the input parameter at each iteration of the 
while loop hence it never returns.

Is it possible ?
Sep 23 2015
parent reply Justin Whear <justin economicmodeling.com> writes:
On Wed, 23 Sep 2015 20:48:03 +0000, BBasile wrote:

 I was thinking to a general *interleave()* algorithm for any compatible
 Range of Range but I can't find any smart way to process each sub range
 by front
Can you show a sample input and output to clarify what you mean by interleave? It's possible that what you want is std.range.frontTransversal, std.range.transversal, or std.range.transposed.
Sep 23 2015
parent reply BBasile <bb.temp gmx.com> writes:
On Wednesday, 23 September 2015 at 21:04:44 UTC, Justin Whear 
wrote:
 On Wed, 23 Sep 2015 20:48:03 +0000, BBasile wrote:

 I was thinking to a general *interleave()* algorithm for any 
 compatible Range of Range but I can't find any smart way to 
 process each sub range by front
Can you show a sample input and output to clarify what you mean by interleave? It's possible that what you want is std.range.frontTransversal, std.range.transversal, or std.range.transposed.
--- auto r0 = [[0,2],[1,3]]; auto r1 = interleave(r0); assert(r1 = [0,1,2,3]); auto r2 = [[0,3],[1,4],[2,5]]; auto r3 = interleave(r2); assert(r3 = [0,1,2,3,4,5]); --- the fact that the numbers are ordered is just an helper.
Sep 23 2015
next sibling parent BBasile <bb.temp gmx.com> writes:
On Wednesday, 23 September 2015 at 21:17:29 UTC, BBasile wrote:
 On Wednesday, 23 September 2015 at 21:04:44 UTC, Justin Whear 
 wrote:
 On Wed, 23 Sep 2015 20:48:03 +0000, BBasile wrote:

 I was thinking to a general *interleave()* algorithm for any 
 compatible Range of Range but I can't find any smart way to 
 process each sub range by front
Can you show a sample input and output to clarify what you mean by interleave? It's possible that what you want is std.range.frontTransversal, std.range.transversal, or std.range.transposed.
--- auto r0 = [[0,2],[1,3]]; auto r1 = interleave(r0); assert(r1 = [0,1,2,3]); auto r2 = [[0,3],[1,4],[2,5]]; auto r3 = interleave(r2); assert(r3 = [0,1,2,3,4,5]); --- the fact that the numbers are ordered is just an helper.
just imagine that there are double equal symbols in the assertions...
Sep 23 2015
prev sibling parent reply Justin Whear <justin economicmodeling.com> writes:
On Wed, 23 Sep 2015 21:17:27 +0000, BBasile wrote:

 On Wednesday, 23 September 2015 at 21:04:44 UTC, Justin Whear wrote:
 On Wed, 23 Sep 2015 20:48:03 +0000, BBasile wrote:

 I was thinking to a general *interleave()* algorithm for any
 compatible Range of Range but I can't find any smart way to process
 each sub range by front
Can you show a sample input and output to clarify what you mean by interleave? It's possible that what you want is std.range.frontTransversal, std.range.transversal, or std.range.transposed.
--- auto r0 = [[0,2],[1,3]]; auto r1 = interleave(r0); assert(r1 = [0,1,2,3]); auto r2 = [[0,3],[1,4],[2,5]]; auto r3 = interleave(r2); assert(r3 = [0,1,2,3,4,5]); --- the fact that the numbers are ordered is just an helper.
OK, I think what you're after is std.range.roundRobin.
Sep 23 2015
parent reply BBasile <bb.temp gmx.com> writes:
On Wednesday, 23 September 2015 at 21:24:22 UTC, Justin Whear 
wrote:
 On Wed, 23 Sep 2015 21:17:27 +0000, BBasile wrote:

 On Wednesday, 23 September 2015 at 21:04:44 UTC, Justin Whear 
 wrote:
 On Wed, 23 Sep 2015 20:48:03 +0000, BBasile wrote:

 I was thinking to a general *interleave()* algorithm for any 
 compatible Range of Range but I can't find any smart way to 
 process each sub range by front
Can you show a sample input and output to clarify what you mean by interleave? It's possible that what you want is std.range.frontTransversal, std.range.transversal, or std.range.transposed.
--- auto r0 = [[0,2],[1,3]]; auto r1 = interleave(r0); assert(r1 = [0,1,2,3]); auto r2 = [[0,3],[1,4],[2,5]]; auto r3 = interleave(r2); assert(r3 = [0,1,2,3,4,5]); --- the fact that the numbers are ordered is just an helper.
OK, I think what you're after is std.range.roundRobin.
--- import std.range; auto interleave(RoR)(RoR r) { return r.transposed.join; } void main() { auto r0 = [[0,2],[1,3]]; auto r1 = interleave(r0); assert(r1 == [0,1,2,3]); auto r2 = [[0,3],[1,4],[2,5]]; auto r3 = interleave(r2); assert(r3 == [0,1,2,3,4,5]); } -- thx, but as you was suposing initially 'transposed' works. didn't know this function before. works fine.
Sep 23 2015
parent Martin Nowak <code dawg.eu> writes:
On Wednesday, 23 September 2015 at 21:30:37 UTC, BBasile wrote:
 auto interleave(RoR)(RoR r)
 {
     return r.transposed.join;
If you use joiner it will even be lazy and avoid the allocation.
Sep 23 2015