In List§
See primary documentation in context for routine categorize
multi method categorize() multi method categorize(Whatever) multi method categorize($test, :$into!, :&as) multi method categorize($test, :&as) multi categorize($test, +items, :$into!, *%named ) multi categorize($test, +items, *%named )
These methods are directly inherited from Any
; see Any.list
for more examples.
This routine transforms a list of values into a hash representing the categorizations of those values according to $test
, which is called once for every element in the list; each hash key represents one possible categorization for one or more of the incoming list values, and the corresponding hash value contains an array of those list values categorized by the $test
, acting like a mapper, into the category of the associated key.
Note that, unlike classify, which assumes that the return value of the mapper is a single value, categorize
always assumes that the return value of the mapper is a list of categories that are appropriate to the current value.
Example:
sub mapper(Int $i) returns List { $i %% 2 ?? 'even' !! 'odd', $i.is-prime ?? 'prime' !! 'not prime' } say categorize &mapper, (1, 7, 6, 3, 2); # OUTPUT: «{even => [6 2], not prime => [1 6], odd => [1 7 3], prime => [7 3 2]}»
In Any§
See primary documentation in context for routine categorize
multi method categorize() multi method categorize(Whatever) multi method categorize($test, :$into!, :&as) multi method categorize($test, :&as) multi categorize($test, +items, :$into!, *%named ) multi categorize($test, +items, *%named )
The first form will always fail. The second form classifies on the identity of the given object, which usually only makes sense in combination with the :&as
argument.
In its simplest form, it uses a $test
whose result will be used as a key; the values of the key will be an array of the elements that produced that key as a result of the test.
say (1..13).categorize( * %% 3); say categorize( * %% 3, 1..13) # OUTPUT: «{False => [1 2 4 5 7 8 10 11 13], True => [3 6 9 12]}»
The :as
argument will normalize before categorizing
say categorize( * %% 3, -5..5, as => &abs ) # OUTPUT: «{False => [5 4 2 1 1 2 4 5], True => [3 0 3]}»
The $into
associative argument can be used to put the result instead of returning a new Hash
.
my %leap-years; my @years = (2002..2009).map( { Date.new( $_~"-01-01" ) } ); @years.categorize( *.is-leap-year , into => %leap-years ); say %leap-years # OUTPUT: # «{ False # => [2002-01-01 2003-01-01 2005-01-01 2006-01-01 2007-01-01 2009-01-01], # True => [2004-01-01 2008-01-01]}»
The function used to categorize can return an array indicating all possible bins their argument can be put into:
sub divisible-by( Int $n --> Array(Seq) ) { gather { for <2 3 5 7> { take $_ if $n %% $_; } } } say (3..13).categorize( &divisible-by ); # OUTPUT: # «{2 => [4 6 8 10 12], 3 => [3 6 9 12], 5 => [5 10], 7 => [7]}»
In this case, every number in the range is classified in as many bins as it can be divided by.
Support for using Whatever
as the test was added in Rakudo compiler version 2023.02.