File Coverage

blib/lib/List/GroupBy.pm
Criterion Covered Total %
statement 37 37 100.0
branch 10 10 100.0
condition 16 19 84.2
subroutine 6 6 100.0
pod 1 1 100.0
total 70 73 95.8


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