File Coverage

blib/lib/Hash/MoreUtils.pm
Criterion Covered Total %
statement 96 97 98.9
branch 20 24 83.3
condition n/a
subroutine 20 20 100.0
pod 10 10 100.0
total 146 151 96.6


line stmt bran cond sub pod time code
1             package Hash::MoreUtils;
2              
3 2     2   52291 use strict;
  2         5  
  2         68  
4 2     2   9 use warnings;
  2         4  
  2         57  
5 2     2   10 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
  2         7  
  2         3558  
6 2     2   36 use Scalar::Util qw(blessed);
  2         4  
  2         823  
7              
8             require Exporter;
9              
10             @ISA = qw(Exporter);
11              
12             %EXPORT_TAGS = (
13             all => [
14             qw(slice slice_def slice_exists slice_grep),
15             qw(slice_map slice_def_map slice_exists_map slice_grep_map),
16             qw(hashsort safe_reverse)
17             ],
18             );
19              
20             @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } );
21              
22             $VERSION = '0.05';
23              
24             =head1 NAME
25              
26             Hash::MoreUtils - Provide the stuff missing in Hash::Util
27              
28             =head1 SYNOPSIS
29              
30             use Hash::MoreUtils qw(slice slice_def slice_exists slice_grep
31             hashsort
32             );
33              
34             =head1 DESCRIPTION
35              
36             Similar to C<< List::MoreUtils >>, C<< Hash::MoreUtils >>
37             contains trivial but commonly-used functionality for hashes.
38              
39             =head1 FUNCTIONS
40              
41             =head2 C HASHREF[, LIST]
42              
43             Returns a hash containing the (key, value) pair for every
44             key in LIST.
45              
46             If no C is given, all keys are assumed as C.
47              
48             =head2 C HASHREF[, LIST]
49              
50             As C, but only includes keys whose values are
51             defined.
52              
53             If no C is given, all keys are assumed as C.
54              
55             =head2 C HASHREF[, LIST]
56              
57             As C but only includes keys which exist in the
58             hashref.
59              
60             If no C is given, all keys are assumed as C.
61              
62             =head2 C BLOCK, HASHREF[, LIST]
63              
64             As C, with an arbitrary condition.
65              
66             If no C is given, all keys are assumed as C.
67              
68             Unlike C, the condition is not given aliases to
69             elements of anything. Instead, C<< %_ >> is set to the
70             contents of the hashref, to avoid accidentally
71             auto-vivifying when checking keys or values. Also,
72             'uninitialized' warnings are turned off in the enclosing
73             scope.
74              
75             =cut
76              
77             sub slice
78             {
79 3     3 1 19 my ( $href, @list ) = @_;
80 3 100       14 @list and return map { $_ => $href->{$_} } @list;
  3         22  
81 1         2 %{$href};
  1         9  
82             }
83              
84             sub slice_exists
85             {
86 3     3 1 9 my ( $href, @list ) = @_;
87 3 100       13 @list or @list = keys %{$href};
  2         9  
88 3         9 return map { $_ => $href->{$_} } grep {exists( $href->{$_} ) } @list;
  8         37  
  9         21  
89             }
90              
91             sub slice_def
92             {
93 4     4 1 12 my ( $href, @list ) = @_;
94 4 100       114 @list or @list = keys %{$href};
  3         12  
95 4         9 return map { $_ => $href->{$_} } grep { defined( $href->{$_} ) } @list;
  7         35  
  12         28  
96             }
97              
98             sub slice_grep (&@)
99             {
100 2     2 1 7 my ( $code, $href, @list ) = @_;
101 2         2 local %_ = %{$href};
  2         9  
102 2 50       13 @list or @list = keys %{$href};
  2         22  
103 2     2   12 no warnings 'uninitialized';
  2         4  
  2         634  
104 2         6 return map { ( $_ => $_{$_} ) } grep { $code->($_) } @list;
  3         23  
  6         31  
105             }
106              
107             =head2 C HASHREF[, MAP]
108              
109             Returns a hash containing the (key, value) pair for every
110             key in C.
111              
112             If no C is given, all keys of C are assumed mapped to theirself.
113              
114             =head2 C HASHREF[, MAP]
115              
116             As C, but only includes keys whose values are
117             defined.
118              
119             If no C is given, all keys of C are assumed mapped to theirself.
120              
121             =head2 C HASHREF[, MAP]
122              
123             As C but only includes keys which exist in the
124             hashref.
125              
126             If no C is given, all keys of C are assumed mapped to theirself.
127              
128             =head2 C BLOCK, HASHREF[, MAP]
129              
130             As C, with an arbitrary condition.
131              
132             If no C is given, all keys of C are assumed mapped to theirself.
133              
134             Unlike C, the condition is not given aliases to
135             elements of anything. Instead, C<< %_ >> is set to the
136             contents of the hashref, to avoid accidentally
137             auto-vivifying when checking keys or values. Also,
138             'uninitialized' warnings are turned off in the enclosing
139             scope.
140              
141             =cut
142              
143             sub slice_map
144             {
145 3     3 1 9 my ( $href, %map ) = @_;
146 3 100       13 %map and return map { $map{$_} => $href->{$_} } keys %map;
  3         20  
147 1         2 %{$href};
  1         9  
148             }
149              
150             sub slice_exists_map
151             {
152 2     2 1 7 my ( $href, %map ) = @_;
153 2 100       12 %map or return slice_exists($href);
154 1         4 return map { $map{$_} => $href->{$_} } grep {exists( $href->{$_} ) } keys %map;
  2         13  
  3         9  
155             }
156              
157             sub slice_def_map
158             {
159 2     2 1 8 my ( $href, %map ) = @_;
160 2 100       9 %map or return slice_def($href);
161 1         4 return map { $map{$_} => $href->{$_} } grep { defined( $href->{$_} ) } keys %map;
  1         8  
  3         8  
162             }
163              
164             sub slice_grep_map (&@)
165             {
166 2     2 1 9 my ( $code, $href, %map ) = @_;
167 2 50       5 %map or return goto &slice_grep;
168 2         3 local %_ = %{$href};
  2         7  
169 2     2   11 no warnings 'uninitialized';
  2         3  
  2         239  
170 2         9 return map { ( $map{$_} => $_{$_} ) } grep { $code->($_) } keys %map;
  3         24  
  6         22  
171             }
172              
173             =head2 C [BLOCK,] HASHREF
174              
175             my @array_of_pairs = hashsort \%hash;
176             my @pairs_by_length = hashsort sub { length($a) <=> length($b) }, \%hash;
177              
178             Returns the (key, value) pairs of the hash, sorted by some
179             property of the keys. By default (if no sort block given), sorts the
180             keys with C.
181              
182             I'm not convinced this is useful yet. If you can think of
183             some way it could be more so, please let me know.
184              
185             =cut
186              
187             sub hashsort
188             {
189 3     3 1 8 my ( $code, $hash ) = @_;
190 3         5 my $cmp;
191 3 100       11 if ( $hash )
192             {
193 2         5 my $package = caller;
194             $cmp = sub {
195 2     2   11 no strict 'refs';
  2         5  
  2         707  
196 6     6   10 local ${$package.'::a'} = $a;
  6         18  
197 6         9 local ${$package.'::b'} = $b;
  6         14  
198 6         14 $code->();
199 2         10 };
200             }
201             else
202             {
203 1         1 $hash = $code;
204 1     3   5 $cmp = sub { $a cmp $b };
  3         8  
205             }
206 3         18 return map { ( $_ => $hash->{$_} ) } sort { $cmp->() } keys %$hash;
  9         47  
  9         23  
207             }
208              
209             =head2 C [BLOCK,] HASHREF
210              
211             my %dup_rev = safe_reverse \%hash
212              
213             sub croak_dup {
214             my ($k, $v, $r) = @_;
215             exists( $r->{$v} ) and
216             croak "Cannot safe reverse: $v would be mapped to both $k and $r->{$v}";
217             $v;
218             };
219             my %easy_rev = save_reverse \&croak_dup, \%hash
220              
221             Returns safely reversed hash (value, key pairs of original hash). If no
222             C<< BLOCK >> is given, following routine will be used:
223              
224             sub merge_dup {
225             my ($k, $v, $r) = @_;
226             return exists( $r->{$v} )
227             ? ( ref($r->{$v}) ? [ @{$r->{$v}}, $k ] : [ $r->{$v}, $k ] )
228             : $k;
229             };
230              
231             The C will be called with 3 arguments:
232              
233             =over 8
234              
235             =item C
236              
237             The key from the C<< ( key, value ) >> pair in the original hash
238              
239             =item C
240              
241             The value from the C<< ( key, value ) >> pair in the original hash
242              
243             =item C
244              
245             Reference to the reversed hash (read-only)
246              
247             =back
248              
249             The C is expected to return the value which will used
250             for the resulting hash.
251              
252             =cut
253              
254             sub safe_reverse
255             {
256 2     2 1 10 my ( $code, $hash ) = @_;
257 2 50       8 unless ($hash)
258             {
259 2         3 $hash = $code;
260             $code = sub {
261 4     4   8 my ($k, $v, $r) = @_;
262 0         0 return exists( $r->{$v} )
263 4 50       21 ? ( ref($r->{$v}) ? [ @{$r->{$v}}, $k ] : [ $r->{$v}, $k ] )
    100          
264             : $k;
265 2         11 };
266             }
267              
268 2         6 my %reverse;
269 2         3 while( my ( $key, $val ) = each %{$hash} )
  6         520  
270             {
271 4         7 $reverse{$val} = &{$code}( $key, $val, \%reverse );
  4         8  
272             }
273 2         20 return %reverse;
274             }
275              
276             1;
277              
278             =head1 AUTHOR
279              
280             Hans Dieter Pearcey, C<< >>,
281             Jens Rehsack, C<< >>
282              
283             =head1 BUGS
284              
285             Please report any bugs or feature requests to
286             C, or through the web interface at
287             L.
288             I will be notified, and then you'll automatically be notified of progress on
289             your bug as I make changes.
290              
291             =head1 SUPPORT
292              
293             You can find documentation for this module with the perldoc command.
294              
295             perldoc Hash::MoreUtils
296              
297             You can also look for information at:
298              
299             =over 4
300              
301             =item * RT: CPAN's request tracker
302              
303             L
304              
305             =item * AnnoCPAN: Annotated CPAN documentation
306              
307             L
308              
309             =item * CPAN Ratings
310              
311             L
312              
313             =item * Search CPAN
314              
315             L
316              
317             =back
318              
319             =head1 ACKNOWLEDGEMENTS
320              
321             =head1 COPYRIGHT & LICENSE
322              
323             Copyright 2005 Hans Dieter Pearcey, all rights reserved.
324             Copyright 2010-2013 Jens Rehsack
325              
326             This program is free software; you can redistribute it and/or modify it
327             under the terms of either: the GNU General Public License as published
328             by the Free Software Foundation; or the Artistic License.
329              
330             See http://dev.perl.org/licenses/ for more information.
331              
332             =cut
333              
334             1; # End of Hash::MoreUtils