digitalmars.D.learn - std.algorithm.reduce on an array of structs
- Colin (24/24) Sep 11 2014 I have this test code:
- Daniel Kozak (17/41) Sep 11 2014 You are try to put uint to Thing. This is corect version:
- Colin (4/51) Sep 11 2014 Ah ok. I get it.
- Daniel Kozak (17/19) Sep 11 2014 a quiet better version:
- Daniel Kozak (3/24) Sep 11 2014 s/quiet/quite/
- bearophile (16/16) Sep 11 2014 Daniel Kozak:
- Daniel Kozak via Digitalmars-d-learn (5/28) Sep 11 2014 V Thu, 11 Sep 2014 14:49:02 +0000
- Daniel Kozak (4/33) Sep 11 2014 or use alias minimum = reduce!"a < b";
- Daniel Kozak (3/5) Sep 11 2014 ok this one does not work
- monarch_dodra (3/9) Sep 11 2014 Yeah, it's actually reduce!"a < b ? a : b"
- monarch_dodra (11/40) Sep 11 2014 There is: http://dlang.org/phobos/std_algorithm.html#.minPos
- Meta (7/14) Sep 11 2014 Even better:
- Colin (4/20) Sep 11 2014 Using the "alias x this" solution would work, but my actual
- Meta (3/6) Sep 11 2014 You could always override opCmp as well:
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (9/33) Sep 11 2014 I think you want to use `filter()` (for both Thing and uint), not
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (3/43) Sep 11 2014 Scratch that, `filter()` doesn't make sense here, of course. The
I have this test code: struct Thing { uint x; } void main(){ uint[] ar1 = [1, 2, 3, 4, 5]; auto min1 = ar1.reduce!((a,b) => a < b); writefln("%s", min1); // prints 1 as expected Thing[] ar2 = [Thing(1), Thing(2), Thing(4)]; auto min2 = ar2.reduce!((a,b) => a.x < b.x); // <- Wont Compile writefln("%s", min2); } The line with "Wont Compile" on it has this error message: /usr/include/dmd/phobos/std/algorithm.d(770): Error: cannot implicitly convert expression (__lambda2(result, front(_param_1))) of type bool to Thing /usr/include/dmd/phobos/std/algorithm.d(791): Error: template instance t.main.reduce!((a, b) => a.x < b.x).reduce!(Thing, Thing[]) error instantiating t.d(16): instantiated from here: reduce!(Thing[]) Any idea what I'm doing wrong here? To me, the operation on ar2 should be pretty much identical to ar1, except for the use of the struct.
Sep 11 2014
On Thursday, 11 September 2014 at 13:06:05 UTC, Colin wrote:I have this test code: struct Thing { uint x; } void main(){ uint[] ar1 = [1, 2, 3, 4, 5]; auto min1 = ar1.reduce!((a,b) => a < b); writefln("%s", min1); // prints 1 as expected Thing[] ar2 = [Thing(1), Thing(2), Thing(4)]; auto min2 = ar2.reduce!((a,b) => a.x < b.x); // <- Wont Compile writefln("%s", min2); } The line with "Wont Compile" on it has this error message: /usr/include/dmd/phobos/std/algorithm.d(770): Error: cannot implicitly convert expression (__lambda2(result, front(_param_1))) of type bool to Thing /usr/include/dmd/phobos/std/algorithm.d(791): Error: template instance t.main.reduce!((a, b) => a.x < b.x).reduce!(Thing, Thing[]) error instantiating t.d(16): instantiated from here: reduce!(Thing[]) Any idea what I'm doing wrong here? To me, the operation on ar2 should be pretty much identical to ar1, except for the use of the struct.You are try to put uint to Thing. This is corect version: import std.stdio; import std.algorithm; struct Thing { uint x; } void main(){ uint[] ar1 = [1, 2, 3, 4, 5]; auto min1 = ar1.reduce!((a,b) => a < b); writefln("%s", min1); // prints 1 as expected Thing[] ar2 = [Thing(1), Thing(2), Thing(4)]; auto min2 = ar2.reduce!((a,b) => a.x < b.x ? a : b); // <- Wont Compile writefln("%s", min2); }
Sep 11 2014
On Thursday, 11 September 2014 at 13:27:39 UTC, Daniel Kozak wrote:On Thursday, 11 September 2014 at 13:06:05 UTC, Colin wrote:Ah ok. I get it. Thanks daniel!I have this test code: struct Thing { uint x; } void main(){ uint[] ar1 = [1, 2, 3, 4, 5]; auto min1 = ar1.reduce!((a,b) => a < b); writefln("%s", min1); // prints 1 as expected Thing[] ar2 = [Thing(1), Thing(2), Thing(4)]; auto min2 = ar2.reduce!((a,b) => a.x < b.x); // <- Wont Compile writefln("%s", min2); } The line with "Wont Compile" on it has this error message: /usr/include/dmd/phobos/std/algorithm.d(770): Error: cannot implicitly convert expression (__lambda2(result, front(_param_1))) of type bool to Thing /usr/include/dmd/phobos/std/algorithm.d(791): Error: template instance t.main.reduce!((a, b) => a.x < b.x).reduce!(Thing, Thing[]) error instantiating t.d(16): instantiated from here: reduce!(Thing[]) Any idea what I'm doing wrong here? To me, the operation on ar2 should be pretty much identical to ar1, except for the use of the struct.You are try to put uint to Thing. This is corect version: import std.stdio; import std.algorithm; struct Thing { uint x; } void main(){ uint[] ar1 = [1, 2, 3, 4, 5]; auto min1 = ar1.reduce!((a,b) => a < b); writefln("%s", min1); // prints 1 as expected Thing[] ar2 = [Thing(1), Thing(2), Thing(4)]; auto min2 = ar2.reduce!((a,b) => a.x < b.x ? a : b); // <- Wont Compile writefln("%s", min2); }
Sep 11 2014
On Thursday, 11 September 2014 at 14:18:31 UTC, Colin wrote:Ah ok. I get it. Thanks daniel!a quiet better version: import std.stdio; import std.algorithm; struct Thing { uint x; alias x this; } void main(){ uint[] ar1 = [1, 2, 3, 4, 5]; auto min1 = ar1.reduce!((a,b) => min(a,b)); writefln("%s", min1); Thing[] ar2 = [Thing(1), Thing(2), Thing(4)]; auto min2 = ar2.reduce!((a,b) => min(a,b)); writefln("%s", min2); }
Sep 11 2014
On Thursday, 11 September 2014 at 14:39:53 UTC, Daniel Kozak wrote:On Thursday, 11 September 2014 at 14:18:31 UTC, Colin wrote:s/quiet/quite/Ah ok. I get it. Thanks daniel!a quiet better version: import std.stdio; import std.algorithm; struct Thing { uint x; alias x this; } void main(){ uint[] ar1 = [1, 2, 3, 4, 5]; auto min1 = ar1.reduce!((a,b) => min(a,b)); writefln("%s", min1); Thing[] ar2 = [Thing(1), Thing(2), Thing(4)]; auto min2 = ar2.reduce!((a,b) => min(a,b)); writefln("%s", min2); }
Sep 11 2014
Daniel Kozak: You can just use min: import std.stdio, std.algorithm; struct Thing { uint x; alias x this; } alias minimum = reduce!min; void main() { immutable ar1 = [10, 20, 30, 40, 50]; ar1.minimum.writeln; immutable ar2 = [Thing(10), Thing(20), Thing(40)]; ar2.minimum.writeln; } Bye, bearophile
Sep 11 2014
V Thu, 11 Sep 2014 14:49:02 +0000 bearophile via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> napsáno:Daniel Kozak: You can just use min: import std.stdio, std.algorithm; struct Thing { uint x; alias x this; } alias minimum = reduce!min; void main() { immutable ar1 = [10, 20, 30, 40, 50]; ar1.minimum.writeln; immutable ar2 = [Thing(10), Thing(20), Thing(40)]; ar2.minimum.writeln; } Bye, bearophileYep, this look the most idiomatic :). Why there is no phobos function for minimum of array(range)?
Sep 11 2014
On Thursday, 11 September 2014 at 14:56:00 UTC, Daniel Kozak via Digitalmars-d-learn wrote:V Thu, 11 Sep 2014 14:49:02 +0000 bearophile via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> napsáno:or use alias minimum = reduce!"a < b"; ;)Daniel Kozak: You can just use min: import std.stdio, std.algorithm; struct Thing { uint x; alias x this; } alias minimum = reduce!min; void main() { immutable ar1 = [10, 20, 30, 40, 50]; ar1.minimum.writeln; immutable ar2 = [Thing(10), Thing(20), Thing(40)]; ar2.minimum.writeln; } Bye, bearophileYep, this look the most idiomatic :). Why there is no phobos function for minimum of array(range)?
Sep 11 2014
On Thursday, 11 September 2014 at 15:07:03 UTC, Daniel Kozak wrote:or use alias minimum = reduce!"a < b"; ;)ok this one does not work
Sep 11 2014
On Thursday, 11 September 2014 at 15:29:18 UTC, Daniel Kozak wrote:On Thursday, 11 September 2014 at 15:07:03 UTC, Daniel Kozak wrote:Yeah, it's actually reduce!"a < b ? a : b"or use alias minimum = reduce!"a < b"; ;)ok this one does not work
Sep 11 2014
On Thursday, 11 September 2014 at 14:56:00 UTC, Daniel Kozak via Digitalmars-d-learn wrote:V Thu, 11 Sep 2014 14:49:02 +0000 bearophile via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> napsáno:To note though: minPos will "find" the position of the smallest element, whereas reduce will accumulate and return the lowest value. That said: alias minmax = reduce!(min, max); auto mm = ar1.minmax(); auto min = mm[0]; auto max = mm[1]; Found both in one line of code, and only 1 iteration of ar1.Daniel Kozak: You can just use min: import std.stdio, std.algorithm; struct Thing { uint x; alias x this; } alias minimum = reduce!min; void main() { immutable ar1 = [10, 20, 30, 40, 50]; ar1.minimum.writeln; immutable ar2 = [Thing(10), Thing(20), Thing(40)]; ar2.minimum.writeln; } Bye, bearophileYep, this look the most idiomatic :). Why there is no phobos function for minimum of array(range)?
Sep 11 2014
On Thursday, 11 September 2014 at 14:49:03 UTC, bearophile wrote:void main() { //... immutable ar2 = [Thing(10), Thing(20), Thing(40)]; ar2.minimum.writeln; } Bye, bearophileEven better: void main { immutable(Thing)[] ar2 = [10, 20, 40]; ar2.minimum.writeln; }
Sep 11 2014
On Thursday, 11 September 2014 at 14:49:03 UTC, bearophile wrote:Daniel Kozak: You can just use min: import std.stdio, std.algorithm; struct Thing { uint x; alias x this; } alias minimum = reduce!min; void main() { immutable ar1 = [10, 20, 30, 40, 50]; ar1.minimum.writeln; immutable ar2 = [Thing(10), Thing(20), Thing(40)]; ar2.minimum.writeln; } Bye, bearophileUsing the "alias x this" solution would work, but my actual struct is not a simple struct, so the comparison isn't exactly (a.x < b.x).
Sep 11 2014
On Thursday, 11 September 2014 at 21:28:59 UTC, Colin wrote:Using the "alias x this" solution would work, but my actual struct is not a simple struct, so the comparison isn't exactly (a.x < b.x).You could always override opCmp as well: http://dlang.org/operatoroverloading.html#compare
Sep 11 2014
On Thursday, 11 September 2014 at 13:06:05 UTC, Colin wrote:I have this test code: struct Thing { uint x; } void main(){ uint[] ar1 = [1, 2, 3, 4, 5]; auto min1 = ar1.reduce!((a,b) => a < b); writefln("%s", min1); // prints 1 as expected Thing[] ar2 = [Thing(1), Thing(2), Thing(4)]; auto min2 = ar2.reduce!((a,b) => a.x < b.x); // <- Wont Compile writefln("%s", min2); } The line with "Wont Compile" on it has this error message: /usr/include/dmd/phobos/std/algorithm.d(770): Error: cannot implicitly convert expression (__lambda2(result, front(_param_1))) of type bool to Thing /usr/include/dmd/phobos/std/algorithm.d(791): Error: template instance t.main.reduce!((a, b) => a.x < b.x).reduce!(Thing, Thing[]) error instantiating t.d(16): instantiated from here: reduce!(Thing[]) Any idea what I'm doing wrong here? To me, the operation on ar2 should be pretty much identical to ar1, except for the use of the struct.I think you want to use `filter()` (for both Thing and uint), not `reduce()`. The former produces a range with only the elements that match the predicate, while the latter produces _one_ element according to the given rules, e.g. my_int_array.reduce!((result,a) => result+a); produces the sum of all elements. In your example, the first use only compiles because `bool` happens to be implicitly convertible to `uint`.
Sep 11 2014
On Thursday, 11 September 2014 at 13:28:37 UTC, Marc Schütz wrote:On Thursday, 11 September 2014 at 13:06:05 UTC, Colin wrote:Scratch that, `filter()` doesn't make sense here, of course. The rest is still valid:I have this test code: struct Thing { uint x; } void main(){ uint[] ar1 = [1, 2, 3, 4, 5]; auto min1 = ar1.reduce!((a,b) => a < b); writefln("%s", min1); // prints 1 as expected Thing[] ar2 = [Thing(1), Thing(2), Thing(4)]; auto min2 = ar2.reduce!((a,b) => a.x < b.x); // <- Wont Compile writefln("%s", min2); } The line with "Wont Compile" on it has this error message: /usr/include/dmd/phobos/std/algorithm.d(770): Error: cannot implicitly convert expression (__lambda2(result, front(_param_1))) of type bool to Thing /usr/include/dmd/phobos/std/algorithm.d(791): Error: template instance t.main.reduce!((a, b) => a.x < b.x).reduce!(Thing, Thing[]) error instantiating t.d(16): instantiated from here: reduce!(Thing[]) Any idea what I'm doing wrong here? To me, the operation on ar2 should be pretty much identical to ar1, except for the use of the struct.I think you want to use `filter()` (for both Thing and uint), not `reduce()`.The former produces a range with only the elements that match the predicate, while the latter produces _one_ element according to the given rules, e.g. my_int_array.reduce!((result,a) => result+a); produces the sum of all elements. In your example, the first use only compiles because `bool` happens to be implicitly convertible to `uint`.
Sep 11 2014