Group an array by property or arbitrary function