digitalmars.D.learn - Most elegant way for split array of struct into components
- Miguel L (22/22) Jul 04 2016 Hello
- =?UTF-8?Q?Ali_=c3=87ehreli?= (56/62) Jul 05 2016 The simplest is to pick the element by std.algorithm.map:
- Miguel L (12/18) Jul 05 2016 Thank you Ali, that works.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (45/53) Jul 05 2016 Yes, but that normally belongs outside the type. Luckily, D's UFCS
Hello I would like advice in the most elegant way for doing this in D: I have something like this: struct A { int x; int y; } A[] my_array; And I would need something like this: assert( my_array[0..n].x == [ my_array[0].x, my_array[1].x, ... my_array[n-1].x ]); assert( my_array[0..n].y == [ my_array[0].y, my_array[1].y, ... my_array[n-1].y ]); assert( my_array.x == [ my_array[0].x, my_array[1].x, ... my_array[$-1].x ]); assert( my_array.y == [ my_array[0].y, my_array[1].y, ... my_array[$-1].y ]); Is it possible to implement something like this in D? If not, which would be the best way to get an array of x or y component of my_array? Thank you
Jul 04 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
Jul 05 2016
On Tuesday, 5 July 2016 at 07:33:40 UTC, Ali Çehreli wrote:On 07/04/2016 11:07 PM, Miguel L wrote:Thank you Ali, that works. On the same subject, could it be possible to implement some class or struct method that works on an array of objects of that class or method? class A { void Y(A[] a){...} } A[] array; array.Y(); Sorry for my ignorance, i am just starting to work in D.[...][...]my_array? The simplest is to pick the element by std.algorithm.map: [...]
Jul 05 2016
On 07/05/2016 01:10 AM, Miguel L wrote:could it be possible to implement some class or struct method that works on an array of objects of that class or method? class A { void Y(A[] a){...} } A[] array; array.Y();Yes, but that normally belongs outside the type. Luckily, D's UFCS feauter lets one call a non-member function as if it's a member function: import std.stdio; import std.algorithm; import std.range; class A { int i; this(int i) { this.i = i; } } // Not a member: void Y(A[] a){ foreach (e; a) { writefln("working with %s", e.i); } } void main() { A[] array = iota(5).map!(i => new A(i)).array; // Can be called like a member: array.Y(); } Still, it's debatable whether an array-processing functions should be executed with the member function syntax. I would write Y(array). When you discover the ranges, you will realize that instead of defining functions like Y that contain explicit loops, combining functions that work with just a single A is more maintainable, scalable, and almost always faster (sometimes you won't need to hold actual arrays of anything). void y(A a) { writefln("working with %s", a.i); } void main() { // Objects are created but not a single array is in sight: iota(5) .map!(i => new A(i)) .each!y; } The output is the same: working with 0 working with 1 working with 2 working with 3 working with 4 Ali
Jul 05 2016