Most elegant way for split array of struct into components

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jul 5 00:33:40 PDT 2016


On 07/04/2016 11:07 PM, Miguel L wrote:

 > struct A
 > {
 > int x;
 > int y;
 > }

 > would be the best way to get an array of x or y component of my_array?

The simplest is to pick the element by std.algorithm.map:

import std.stdio;
import std.range;
import std.array;
import std.algorithm;

struct A {
     int x;
     int y;
}

void main() {
     A[] my_array = iota(3)
                    .map!(i => A(i, 11 * i))
                    .array;

     writeln("The whole array:");
     writeln(my_array);

     writeln("Just the x members");
     auto xs = my_array.map!(a => a.x);
     writeln(xs);

     writeln("Just the y members");
     auto ys = my_array.map!(a => a.y);
     writeln(ys);
}

Prints

The whole array:
[A(0, 0), A(1, 11), A(2, 22)]
Just the x members
[0, 1, 2]
Just the y members
[0, 11, 22]

map has a shortcut: If there is a function foo that takes A, then you 
can do just this:

     writeln(my_array.map!foo);

(foo can be a member function or a non-member function.)

With the great risk of polluting the namespace, here is a draft of 
creating non-member accessor functions automatically:

string memberAccessors(T)() {
     import std.string;
     string accessors;

     foreach(m; __traits(allMembers, T)) {
         accessors ~= format("auto %s(%s a) { return a.%s; }\n", m, 
T.stringof, m);
     }

     return accessors;
}

mixin(memberAccessors!A);

That generates and mixes in accessor functions for each member. A 
pragma(msg) can show what is generated:

pragma(msg, memberAccessors!A);

Prints at compile time:

auto x(A a) { return a.x; }
auto y(A a) { return a.y; }

(Crazy idea. :) )

But then, it's as simple as the following:

     writeln(my_array.map!y);

Ali



More information about the Digitalmars-d-learn mailing list