www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - From [Tuple!(A,B), ...] to Tuple!(A[], B[])

reply foozzer <foozzer gmail.com> writes:
Hi all,

There's something in Phobos for that?

Thank you
Feb 17 2020
next sibling parent Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Monday, 17 February 2020 at 11:07:33 UTC, foozzer wrote:
 Hi all,

 There's something in Phobos for that?

 Thank you
import std.meta : staticMap; import std.typecons : Tuple; // Turn types into arrays alias ToArray(T) = T[]; // Leave everything else the same alias ToArray(T...) = T; // Now apply the above to each element of the Tuple template args: alias ToArrayTuple(T : Tuple!U, U...) = Tuple!(staticMap!(ToArray, U)); unittest { alias A = Tuple!(int, string); assert(is(ToArrayTuple!A == Tuple!(int[], string[]))); alias B = Tuple!(int, "a", string, "b"); assert(is(ToArrayTuple!B == Tuple!(int[], "a", string[], "b"))); } -- Simen
Feb 17 2020
prev sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Monday, 17 February 2020 at 11:07:33 UTC, foozzer wrote:
 Hi all,

 There's something in Phobos for that?

 Thank you
Here you go: import std; // extract the types that make up the tuple auto transposeTuple(T : Tuple!Types[], Types...)(T tuples) { // templated function that extracts the ith field of an array of tuples as an array auto extractArray(int i)() { return tuples.map!(a => a[i]).array; } // return tuple of calls to extractArray, one for each tuple index return tuple(staticMap!(extractArray, aliasSeqOf!(Types.length.iota))); } void main() { Tuple!(int, double)[] array; array ~= tuple(1, 2.0); array ~= tuple(3, 4.0); Tuple!(int[], double[]) tuple = array.transposeTuple; assert(tuple[0] == [1, 3]); assert(tuple[1] == [2.0, 4.0]); }
Feb 17 2020
next sibling parent Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Monday, 17 February 2020 at 11:51:52 UTC, FeepingCreature 
wrote:
 On Monday, 17 February 2020 at 11:07:33 UTC, foozzer wrote:
 Hi all,

 There's something in Phobos for that?

 Thank you
Here you go: import std; // extract the types that make up the tuple auto transposeTuple(T : Tuple!Types[], Types...)(T tuples) { // templated function that extracts the ith field of an array of tuples as an array auto extractArray(int i)() { return tuples.map!(a => a[i]).array; } // return tuple of calls to extractArray, one for each tuple index return tuple(staticMap!(extractArray, aliasSeqOf!(Types.length.iota))); } void main() { Tuple!(int, double)[] array; array ~= tuple(1, 2.0); array ~= tuple(3, 4.0); Tuple!(int[], double[]) tuple = array.transposeTuple; assert(tuple[0] == [1, 3]); assert(tuple[1] == [2.0, 4.0]); }
^^ Do what he said - I misread the title. :) -- Simen
Feb 17 2020
prev sibling parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Monday, 17 February 2020 at 11:51:52 UTC, FeepingCreature 
wrote:
 Here you go:

 import std;

 // extract the types that make up the tuple
 auto transposeTuple(T : Tuple!Types[], Types...)(T tuples)
 {
     // templated function that extracts the ith field of an 
 array of tuples as an array
     auto extractArray(int i)()
     {
         return tuples.map!(a => a[i]).array;
     }
     // return tuple of calls to extractArray, one for each 
 tuple index
     return tuple(staticMap!(extractArray, 
 aliasSeqOf!(Types.length.iota)));
 }

 void main() {
     Tuple!(int, double)[] array;
     array ~= tuple(1, 2.0);
     array ~= tuple(3, 4.0);
     Tuple!(int[], double[]) tuple = array.transposeTuple;
     assert(tuple[0] == [1, 3]);
     assert(tuple[1] == [2.0, 4.0]);
 }
One tiny thing: the above fails for tuples with named fields, like Tuple!(int, "a", string "b"). This code handles that case, and preserves field names: import std.meta : staticMap, aliasSeqOf; import std.typecons : Tuple; import std.range : array, iota; import std.algorithm : map; alias ToArray(T) = T[]; alias ToArray(T...) = T; alias ToArrayTuple(T : Tuple!U, U...) = Tuple!(staticMap!(ToArray, U)); auto transpose(T : Tuple!U, U...)(T[] arr) { auto extract(int i)() { return arr.map!(a => a[i]).array; } return ToArrayTuple!T(staticMap!(extract, aliasSeqOf!(T.Types.length.iota))); } unittest { alias T = Tuple!(int, "a", string, "b"); auto a = [T(1, "a"), T(2, "b")]; assert(a.transpose.a == [1, 2]); assert(a.transpose.b == ["a", "b"]); } -- Simen
Feb 17 2020
parent foozzer <foozzer gmail.com> writes:
On Monday, 17 February 2020 at 12:11:38 UTC, Simen Kjærås wrote:
 On Monday, 17 February 2020 at 11:51:52 UTC, FeepingCreature 
 wrote:
 [...]
One tiny thing: the above fails for tuples with named fields, like Tuple!(int, "a", string "b"). This code handles that case, and preserves field names: [...]
Thank you all
Feb 17 2020