Convert array of tuples into array of arrays.

Ali Çehreli acehreli at yahoo.com
Wed Aug 31 17:26:56 UTC 2022


On 8/31/22 07:34, musculus wrote:
 > Hi. I have an array of tuples that I would like to convert to an array
 > of arrays.

I misunderstood as well and wrote the following program which makes 
separate arrays. You can make an array of arrays from those with the 
following syntax:

   auto arrayOfArrays = [ keys, values ];

Then I wrote a more general program after this first one:

// Compiles slow but is convenient
import std;

auto makeTestTuple(int i) {
   return tuple!("key", "value")((i * 2).to!string,
                                 (double(i) / 10).to!string);
}

void main() {
   auto tuples = iota(10)
                 .map!makeTestTuple
                 .array;

   string[] keys;
   string[] values;

   writeln("Imperative:");

   foreach (t; tuples) {
     keys ~= t.key;
     values ~= t.value;
   }

   writeln(keys);
   writeln(values);

   writeln("Alternative:");
   keys = tuples.map!(t => t.key).array;
   values = tuples.map!(t => t.value).array;
   writeln(keys);
   writeln(values);

   writeln("More generic:");
   keys = tuples.memberArray!"key";
   values = tuples.memberArray!"value";
   writeln(keys);
   writeln(values);
}

auto memberArray(string member, T)(T[] tuples) {
   return tuples.map!(t => mixin("t." ~ member)).array;
}

Here is the second program to have fun and "competitive advantage" with 
D. (That phrase came up recently, so I remembered it here. :) )

// Compiles slow but is convenient
import std;

auto makeTestTuple(int i) {
   return tuple!("key", "value", "somethingElse")(
     (i * 2).to!string,
     (double(i) / 10).to!string,
     i * i);
}

mixin template matchingMember(string name, T) {
   mixin (T.stringof ~ "[] " ~ name ~ ';');
}

template TupleMemberArrays(T) {
   alias types = T.Types;
   alias fieldNames = T.fieldNames;
   enum memberCount = types.length;

   struct TupleMemberArrays {
     static foreach (i; 0 .. memberCount) {
       mixin matchingMember!(fieldNames[i], types[i]);
     }

     this(T[] tuples) {
       foreach (t; tuples) {
         static foreach (i; 0 .. memberCount) {
           mixin (format!q{
               %s ~= t.%s = t[%s];
             }(fieldNames[i], fieldNames[i], i));
         }
       }
     }
   }
}

void main() {
   auto tuples = iota(10)
                 .map!makeTestTuple
                 .array;

   alias S = TupleMemberArrays!(ElementType!(typeof(tuples)));
   auto s = S(tuples);
   writeln(s.key);
   writeln(s.value);
   writeln(s.somethingElse);
}

That second program defines a type that matches the members of a tuple. 
Given a tuple with member names "key", "value", and "somethingElse"; and 
types string, string, int; it generates a struct similar to the following:

struct YourAliasHere {
   string[] key;
   string[] value;
   int[] somethingElse;
}

Limitation: That implementation uses field names, which not all tuples 
use. But it can be changed to generate names file field0, field1, etc. 
when needed.

Ali



More information about the Digitalmars-d-learn mailing list