File Coverage

blib/lib/List/GroupBy.pm
Criterion Covered Total %
statement 38 38 100.0
branch 12 12 100.0
condition 16 19 84.2
subroutine 6 6 100.0
pod 1 1 100.0
total 73 76 96.0


line stmt bran cond sub pod time code
1             package List::GroupBy;
2 3     3   170904 use 5.010001;
  3         36  
3 3     3   17 use strict;
  3         5  
  3         72  
4 3     3   16 use warnings;
  3         6  
  3         145  
5              
6             our $VERSION = "0.03";
7              
8 3     3   17 use Exporter qw( import );
  3         11  
  3         166  
9              
10             our @EXPORT_OK = qw( groupBy );
11              
12 3     3   18 use Carp;
  3         6  
  3         1327  
13              
14             my $nop = sub { $_[0] };
15              
16             sub groupBy {
17 18     18 1 141769 my ( $options, @list ) = @_;
18              
19 18 100       65 $options = ref $options eq "ARRAY" ? { keys => $options } : $options;
20              
21 18 100       125 croak "missing grouping keys" unless ref $options->{keys} eq "ARRAY";
22              
23 14         23 my @keys = @{ $options->{keys} };
  14         49  
24            
25 14   100     61 my $default = $options->{defaults} // {};
26              
27 14 100       61 croak "defaults should be a hashref" unless ref $default eq "HASH";
28              
29 12   100     42 $options->{operations} //= {};
30              
31 12 100       62 croak "operations should be a hashref" unless ref $options->{operations} eq "HASH";
32              
33              
34             my %op = map {
35 10   66     25 my $operation = $options->{operations}->{ $_ } // $nop;
  18         59  
36              
37 18 100       59 croak "operation defined should be an anonymous sub" unless ref $operation eq "CODE";
38              
39 16         50 $_ => $operation;
40             } @keys;
41              
42              
43 8         19 my $groupings = {};
44              
45 8         17 my $leaf = pop @keys;
46              
47 8         29 foreach my $item (@list) {
48 40         89 my $current = $groupings;
49              
50 40         72 foreach my $key ( @keys ) {
51 40   100     169 my $branch = $op{ $key }->( $item->{ $key } // $default->{ $key } // '' );
      100        
52              
53 40   100     146 $current = $current->{ $branch } //= {};
54             }
55              
56 40   66     123 my $leafNode = $op{ $leaf }->( $item->{$leaf} // $default->{ $leaf } // '' );
      50        
57 40         51 push @{ $current->{ $leafNode } }, $item;
  40         97  
58             }
59            
60 8 100       61 return wantarray ? %$groupings : $groupings;
61             }
62              
63              
64             1;
65             __END__