Filtering a tuple of containers with indices

anonymous via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Nov 17 07:48:10 PST 2015


On 17.11.2015 15:32, maik klein wrote:
> template tupIndexToRange(alias Tup, Indices...){
[snip]

I don't quite understand how that code is supposed to work. Maybe 
there's just some detail missing, but it could also be that your 
approach can't work.

> This is roughly what I want to achieve
>
>    alias Integrals = AliasSeq!(Array!int, Array!float, Array!double);
>    Integrals integrals;
>    integrals[0].insertBack(1);
>    integrals[1].insertBack(2);
>    integrals[2].insertBack(3);
>
>    auto range = zip(tuple(integrals[0][],integrals[1][]).expand);
>    writeln(range);
>    foreach(e;range){
>      writeln("element: ",e);
>    }
> But instead of "auto range =
> zip(tuple(integrals[0][],integrals[1][]).expand);" I want it to be
> generic "auto range = zip(tupIndexToRange!(integrals, AliasSeq!(0,
> 1)).expand);"

I think the problem can be split up into two independent tasks:

1) Select fields of a tuple by indices (to drop `integrals[3]`).
2) A "map" function for tuples (to apply `[]` to the selected arrays).

Here are two quick implementations of those applied to your problem:

----
template selectFromTuple(indices ...)
{
     auto selectFromTuple(Types...)(Types values)
     {
         import std.typecons: tuple, Tuple;
         static if (indices.length == 0) return Tuple!()();
         else
         {
             enum headIndex = indices[0];
             auto tail = .selectFromTuple!(indices[1 .. $])(values);
             return tuple(values[headIndex], tail.expand);
         }
     }
}

auto mapTuple(alias op, Types ...)(Types values)
{
     import std.meta: staticMap;
     import std.typecons: tuple;

     alias ResultType(T) = typeof(op(T.init));
     alias ResultTypes = staticMap!(ResultType, Types);

     ResultTypes results;
     foreach (i, v; values) results[i] = op(v);
     return tuple(results);
}

void main()
{
   import std.container.array;
   import std.meta: AliasSeq;
   import std.range: zip;
   import std.stdio: writeln;

   alias Integrals = AliasSeq!(Array!int, Array!float, Array!double);
   Integrals integrals;
   integrals[0].insertBack(1);
   integrals[1].insertBack(2);
   integrals[2].insertBack(3);

   auto range = integrals
     .selectFromTuple!(0, 1).expand
     .mapTuple!(a => a[]).expand
     .zip;

   writeln(range);
   foreach(e;range){
     writeln("element: ",e);
   }
}
----

That looks a lot like range based programming, which makes me think that 
there could be a way to use actual range algorithms from std.algorithm 
for this. But I don't see how.


More information about the Digitalmars-d-learn mailing list