| |
| Posted by Atila Neves in reply to Edwin van Leeuwen | PermalinkReply |
|
Atila Neves
Posted in reply to Edwin van Leeuwen
| This works:
import std.range;
auto groupBy(alias func, R)(R values)
if (isInputRange!R)
{
alias K = typeof(func(values.front));
alias V = ElementType!R[];
V[K] grouped;
foreach(value; values) grouped[func(value)] ~= value;
return grouped;
}
unittest {
struct Test {
string a;
double b;
}
auto values = [Test( "a", 1 ), Test( "a", 2 ), Test( "b", 3 )];
auto grouped = values.groupBy!(a => a.a);
assert( grouped["a"].length == 2 );
assert( grouped["a"][1].b == 2 );
assert( grouped["b"].length == 1 );
assert( grouped["b"][0].b == 3 );
}
Atila
On Thursday, 16 October 2014 at 08:04:08 UTC, Edwin van Leeuwen wrote:
> I am trying to implement a groupBy function that groups by the return type of a predicate. Currently I have to define the returntype of the predicate for it to compile. Is there a way to get the return type at compile time and use it.
>
> The code:
> V[K] groupBy( alias func, K, V )( V values )
> {
> V[K] grouped;
> foreach ( value ; values ) {
> grouped[func( value )] ~= value;
> }
> return grouped;
> }
>
> unittest {
> struct Test {
> string a;
> double b;
> }
>
> auto values = [Test( "a", 1 ), Test( "a", 2 ), Test( "b", 3 )];
> auto grouped = values.groupBy!( (a) => a.a, string );
> assert( grouped["a"].length == 2 );
> assert( grouped["a"][1].b == 2 );
> assert( grouped["b"].length == 1 );
> assert( grouped["b"][0].b == 3 );
> }
>
> So the above works, but I need to call it with:
> values.groupBy!( (a) => a.a, string );
> Ideally I would call it instead with:
> values.groupBy!( (a) => a.a )
> and it would infer that the template K needs to be a string, since that is the return type of (a) => a.a.
>
> Cheers,
>
> Edwin
|