File Coverage

blib/lib/Hash/MoreUtils.pm
Criterion Covered Total %
statement 151 151 100.0
branch 46 46 100.0
condition n/a
subroutine 29 29 100.0
pod 19 19 100.0
total 245 245 100.0


line stmt bran cond sub pod time code
1             package Hash::MoreUtils;
2              
3 2     2   117040 use strict;
  2         13  
  2         50  
4 2     2   9 use warnings;
  2         3  
  2         61  
5 2     2   11 use vars qw(@EXPORT_OK %EXPORT_TAGS $VERSION);
  2         3  
  2         139  
6 2     2   10 use base 'Exporter';
  2         4  
  2         1384  
7              
8             %EXPORT_TAGS = (
9             all => [
10             qw(slice slice_def slice_exists slice_without slice_missing),
11             qw(slice_notdef slice_true slice_false slice_grep),
12             qw(slice_map slice_def_map slice_exists_map slice_missing_map),
13             qw(slice_notdef_map slice_true_map slice_false_map slice_grep_map),
14             qw(hashsort safe_reverse)
15             ],
16             );
17              
18             @EXPORT_OK = (@{$EXPORT_TAGS{all}});
19              
20             $VERSION = '0.06';
21              
22             =head1 NAME
23              
24             Hash::MoreUtils - Provide the stuff missing in Hash::Util
25              
26             =head1 SYNOPSIS
27              
28             use Hash::MoreUtils qw(:all);
29            
30             my %h = (foo => "bar", FOO => "BAR", true => 1, false => 0);
31             my %s = slice \%h, qw(true false); # (true => 1, false => 0)
32             my %f = slice_false \%h; # (false => 0)
33             my %u = slice_grep { $_ =~ m/^[A-Z]/ }, \%h; # (FOO => "BAR")
34            
35             my %r = safe_reverse \%h; # (bar => "foo", BAR => "FOO", 0 => "false", 1 => "true")
36              
37             =head1 DESCRIPTION
38              
39             Similar to L, C contains trivial
40             but commonly-used functionality for hashes. The primary focus for
41             the moment is providing a common API - speeding up by XS is far
42             away at the moment.
43              
44             =head1 FUNCTIONS
45              
46             =head2 C HASHREF[, LIST]
47              
48             Returns a hash containing the (key, value) pair for every
49             key in LIST.
50              
51             If no C is given, all keys are assumed as C.
52              
53             =head2 C HASHREF[, LIST]
54              
55             As C, but only includes keys whose values are
56             defined.
57              
58             If no C is given, all keys are assumed as C.
59              
60             =head2 C HASHREF[, LIST]
61              
62             As C but only includes keys which exist in the
63             hashref.
64              
65             If no C is given, all keys are assumed as C.
66              
67             =head2 C HASHREF[, LIST ]
68              
69             As C but without any (key/value) pair whose key is
70             in LIST.
71              
72             If no C is given, in opposite to slice an empty list
73             is assumed, thus nothing will be deleted.
74              
75             =head2 C HASHREF[, LIST]
76              
77             Returns a HASH containing the (key => undef) pair for every
78             C element (as key) that does not exist hashref.
79              
80             If no C is given there are obviously no non-existent
81             keys in C so the returned HASH is empty.
82              
83             =head2 C HASHREF[, LIST]
84              
85             Searches for undefined slices with the given C
86             elements as keys in the given C.
87             Returns a C containing the slices (key -> undef)
88             for every undefined item.
89              
90             To search for undefined slices C needs a
91             C with items to search for (as keys). If no C
92             is given it returns an empty C even when the given
93             C contains undefined slices.
94              
95             =head2 C HASHREF[, LIST]
96              
97             A special C which returns only those elements
98             of the hash which's values evaluates to C.
99              
100             If no C is given, all keys are assumed as C.
101              
102             =head2 C HASHREF[, LIST]
103              
104             A special C which returns only those elements
105             of the hash which's values evaluates to C.
106              
107             If no C is given, all keys are assumed as C.
108              
109             =head2 C BLOCK, HASHREF[, LIST]
110              
111             As C, with an arbitrary condition.
112              
113             If no C is given, all keys are assumed as C.
114              
115             Unlike C, the condition is not given aliases to
116             elements of anything. Instead, C<< %_ >> is set to the
117             contents of the hashref, to avoid accidentally
118             auto-vivifying when checking keys or values. Also,
119             'uninitialized' warnings are turned off in the enclosing
120             scope.
121              
122             =cut
123              
124             sub slice
125             {
126 3     3 1 91 my ($href, @list) = @_;
127 3 100       9 @list and return map { $_ => $href->{$_} } @list;
  3         18  
128 1         2 return %{$href};
  1         9  
129             }
130              
131             sub slice_exists
132             {
133 3     3 1 9 my ($href, @list) = @_;
134 3 100       9 @list or @list = keys %{$href};
  2         6  
135 3         7 return map { $_ => $href->{$_} } grep { exists($href->{$_}) } @list;
  8         29  
  9         18  
136             }
137              
138             sub slice_without
139             {
140 4     4 1 12 my ($href, @list) = @_;
141 4 100       9 @list or return %{$href};
  1         8  
142 3         4 local %_ = %{$href};
  3         19  
143 3         9 delete $_{$_} for @list;
144 3         15 return %_;
145             }
146              
147             sub slice_def
148             {
149 5     5 1 607 my ($href, @list) = @_;
150 5 100       15 @list or @list = keys %{$href};
  4         12  
151 5         14 return map { $_ => $href->{$_} } grep { defined($href->{$_}) } @list;
  9         36  
  15         34  
152             }
153              
154             sub slice_missing
155             {
156 8     8 1 421 my ($href, @list) = @_;
157 8 100       36 @list or return ();
158 2         4 return map { $_ => undef } grep { !exists($href->{$_}) } @list;
  2         13  
  4         10  
159             }
160              
161             sub slice_notdef
162             {
163 5     5 1 13 my ($href, @list) = @_;
164 5 100       26 @list or return ();
165 1         3 return map { $_ => undef } grep { !defined($href->{$_}) } @list;
  2         9  
  4         8  
166             }
167              
168             sub slice_true
169             {
170 4     4 1 13 my ($href, @list) = @_;
171 4 100       11 @list or @list = keys %{$href};
  2         7  
172 4 100       9 return map { $_ => $href->{$_} } grep { defined $href->{$_} and $href->{$_} } @list;
  10         37  
  21         65  
173             }
174              
175             sub slice_false
176             {
177 4     4 1 10 my ($href, @list) = @_;
178 4 100       12 @list or @list = keys %{$href};
  2         7  
179 4         10 return map { $_ => $href->{$_} } grep { not $href->{$_} } @list;
  12         49  
  23         42  
180             }
181              
182             ## no critic (Subroutines::ProhibitSubroutinePrototypes)
183             sub slice_grep (&@)
184             {
185 4     4 1 12 my ($code, $href, @list) = @_;
186 4         5 local %_ = %{$href};
  4         16  
187 4 100       19 @list or @list = keys %{$href};
  3         9  
188 2     2   13 no warnings 'uninitialized'; ## no critic (TestingAndDebugging::ProhibitNoWarnings)
  2         4  
  2         155  
189 4         8 return map { ($_ => $_{$_}) } grep { $code->($_) } @list;
  5         40  
  12         40  
190             }
191              
192 2     2   11 use warnings;
  2         4  
  2         973  
193              
194             =head2 C HASHREF[, MAP]
195              
196             Returns a hash containing the (key, value) pair for every
197             key in C.
198              
199             If no C is given, all keys of C are assumed mapped to themselves.
200              
201             =head2 C HASHREF[, MAP]
202              
203             As C, but only includes keys whose values are
204             defined.
205              
206             If no C is given, all keys of C are assumed mapped to themselves.
207              
208             =head2 C HASHREF[, MAP]
209              
210             As C but only includes keys which exist in the
211             hashref.
212              
213             If no C is given, all keys of C are assumed mapped to themselves.
214              
215             =head2 C HASHREF[, MAP]
216              
217             As C but checks for missing keys (of C) and map to the value (of C) as key in the returned HASH.
218             The slices of the returned C are always undefined.
219              
220             If no C is given, C will be used on C which will return an empty HASH.
221              
222             =head2 C HASHREF[, MAP]
223              
224             As C but checks for undefined keys (of C) and map to the value (of C) as key in the returned HASH.
225              
226             If no C is given, C will be used on C which will return an empty HASH.
227              
228             =head2 C HASHREF[, MAP]
229              
230             As C, but only includes pairs whose values are
231             C.
232              
233             If no C is given, all keys of C are assumed mapped to themselves.
234              
235             =head2 C HASHREF[, MAP]
236              
237             As C, but only includes pairs whose values are
238             C.
239              
240             If no C is given, all keys of C are assumed mapped to themselves.
241              
242             =head2 C BLOCK, HASHREF[, MAP]
243              
244             As C, with an arbitrary condition.
245              
246             If no C is given, all keys of C are assumed mapped to themselves.
247              
248             Unlike C, the condition is not given aliases to
249             elements of anything. Instead, C<< %_ >> is set to the
250             contents of the hashref, to avoid accidentally
251             auto-vivifying when checking keys or values. Also,
252             'uninitialized' warnings are turned off in the enclosing
253             scope.
254              
255             =cut
256              
257             sub slice_map
258             {
259 3     3 1 9 my ($href, %map) = @_;
260 3 100       10 %map and return map { $map{$_} => $href->{$_} } keys %map;
  3         17  
261 1         2 return %{$href};
  1         8  
262             }
263              
264             sub slice_exists_map
265             {
266 2     2 1 7 my ($href, %map) = @_;
267 2 100       8 %map or return slice_exists($href);
268 1         5 return map { $map{$_} => $href->{$_} } grep { exists($href->{$_}) } keys %map;
  2         11  
  3         6  
269             }
270              
271             sub slice_missing_map
272             {
273 5     5 1 15 my ($href, %map) = @_;
274 5 100       17 %map or return slice_missing($href);
275 2         10 return map { $map{$_} => undef } grep { !exists($href->{$_}) } keys %map;
  2         18  
  4         16  
276             }
277              
278             sub slice_notdef_map
279             {
280 5     5 1 14 my ($href, %map) = @_;
281 5 100       14 %map or return slice_notdef($href);
282 2         6 return map { $map{$_} => $href->{$_} } grep { !defined($href->{$_}) } keys %map;
  2         14  
  4         10  
283             }
284              
285             sub slice_def_map
286             {
287 2     2 1 9 my ($href, %map) = @_;
288 2 100       9 %map or return slice_def($href);
289 1         4 return map { $map{$_} => $href->{$_} } grep { defined($href->{$_}) } keys %map;
  1         6  
  3         8  
290             }
291              
292             sub slice_true_map
293             {
294 3     3 1 12 my ($href, %map) = @_;
295 3 100       10 %map or return slice_true($href);
296 2 100       45 return map { $map{$_} => $href->{$_} } grep { defined $href->{$_} and $href->{$_} } keys %map;
  5         24  
  8         34  
297             }
298              
299             sub slice_false_map
300             {
301 3     3 1 17 my ($href, %map) = @_;
302 3 100       13 %map or return slice_false($href);
303 2         8 return map { $map{$_} => $href->{$_} } grep { not $href->{$_} } keys %map;
  8         34  
  12         30  
304             }
305              
306             sub slice_grep_map (&@)
307             {
308 3     3 1 15 my ($code, $href, %map) = @_;
309 3 100       16 %map or return goto &slice_grep;
310 2         15 local %_ = %{$href};
  2         13  
311 2     2   12 no warnings 'uninitialized'; ## no critic (TestingAndDebugging::ProhibitNoWarnings)
  2         3  
  2         143  
312 2         9 return map { ($map{$_} => $_{$_}) } grep { $code->($_) } keys %map;
  3         31  
  6         30  
313             }
314              
315 2     2   11 use warnings;
  2         4  
  2         183  
316              
317             =head2 C [BLOCK,] HASHREF
318              
319             my @array_of_pairs = hashsort \%hash;
320             my @pairs_by_length = hashsort sub { length($a) <=> length($b) }, \%hash;
321              
322             Returns the (key, value) pairs of the hash, sorted by some
323             property of the keys. By default (if no sort block given), sorts the
324             keys with C.
325              
326             I'm not convinced this is useful yet. If you can think of
327             some way it could be more so, please let me know.
328              
329             =cut
330              
331             sub hashsort
332             {
333 3     3 1 9 my ($code, $hash) = @_;
334 3 100       9 $hash or return map { ($_ => $hash->{$_}) } sort { $a cmp $b } keys %{$hash = $code};
  3         14  
  3         10  
  1         9  
335              
336             # Localise $a, $b
337             my ($caller_a, $caller_b) = do
338 2         5 {
339 2         5 my $pkg = caller();
340             ## no critic (TestingAndDebugging::ProhibitNoStrict)
341 2     2   11 no strict 'refs';
  2         10  
  2         496  
342 2         4 (\*{$pkg . '::a'}, \*{$pkg . '::b'});
  2         9  
  2         10  
343             };
344              
345             ## no critic (Variables::RequireInitializationForLocalVars)
346 2         7 local (*$caller_a, *$caller_b);
347             ## no critic (BuiltinFunctions::RequireSimpleSortBlock)
348 2         10 return map { ($_ => $hash->{$_}) } sort { (*$caller_a, *$caller_b) = (\$a, \$b); $code->(); } keys %$hash;
  6         45  
  6         21  
  6         14  
349             }
350              
351             =head2 C [BLOCK,] HASHREF
352              
353             my %dup_rev = safe_reverse \%hash
354              
355             sub croak_dup {
356             my ($k, $v, $r) = @_;
357             exists( $r->{$v} ) and
358             croak "Cannot safe reverse: $v would be mapped to both $k and $r->{$v}";
359             $v;
360             };
361             my %easy_rev = safe_reverse \&croak_dup, \%hash
362              
363             Returns safely reversed hash (value, key pairs of original hash). If no
364             C<< BLOCK >> is given, following routine will be used:
365              
366             sub merge_dup {
367             my ($k, $v, $r) = @_;
368             return exists( $r->{$v} )
369             ? ( ref($r->{$v}) ? [ @{$r->{$v}}, $k ] : [ $r->{$v}, $k ] )
370             : $k;
371             };
372              
373             The C will be called with 3 arguments:
374              
375             =over 8
376              
377             =item C
378              
379             The key from the C<< ( key, value ) >> pair in the original hash
380              
381             =item C
382              
383             The value from the C<< ( key, value ) >> pair in the original hash
384              
385             =item C
386              
387             Reference to the reversed hash (read-only)
388              
389             =back
390              
391             The C is expected to return the value which will used
392             for the resulting hash.
393              
394             =cut
395              
396             sub safe_reverse
397             {
398 4     4 1 610 my ($code, $hash) = @_;
399 4 100       14 unless ($hash)
400             {
401 3         5 $hash = $code;
402             $code = sub {
403 7     7   15 my ($k, $v, $r) = @_;
404             return exists($r->{$v})
405 7 100       34 ? (ref($r->{$v}) ? [@{$r->{$v}}, $k] : [$r->{$v}, $k])
  1 100       5  
406             : $k;
407 3         34 };
408             }
409              
410 4         10 my %reverse;
411 4         8 while (my ($key, $val) = each %{$hash})
  13         57  
412             {
413 9         16 $reverse{$val} = &{$code}($key, $val, \%reverse);
  9         21  
414             }
415 4         35 return %reverse;
416             }
417              
418             1;
419              
420             =head1 AUTHOR
421              
422             Hans Dieter Pearcey, C<< >>,
423             Jens Rehsack, C<< >>
424              
425             =head1 BUGS
426              
427             Please report any bugs or feature requests to
428             C, or through the web interface at
429             L.
430             I will be notified, and then you'll automatically be notified of progress on
431             your bug as I make changes.
432              
433             =head1 SUPPORT
434              
435             You can find documentation for this module with the perldoc command.
436              
437             perldoc Hash::MoreUtils
438              
439             You can also look for information at:
440              
441             =over 4
442              
443             =item * RT: CPAN's request tracker
444              
445             L
446              
447             =item * AnnoCPAN: Annotated CPAN documentation
448              
449             L
450              
451             =item * CPAN Ratings
452              
453             L
454              
455             =item * Search CPAN
456              
457             L
458              
459             =back
460              
461             =head1 ACKNOWLEDGEMENTS
462              
463             =head1 COPYRIGHT & LICENSE
464              
465             Copyright 2005 Hans Dieter Pearcey, all rights reserved.
466             Copyright 2010-2018 Jens Rehsack
467              
468             This program is free software; you can redistribute it and/or modify it
469             under the terms of either: the GNU General Public License as published
470             by the Free Software Foundation; or the Artistic License.
471              
472             See http://dev.perl.org/licenses/ for more information.
473              
474             =cut
475              
476             1; # End of Hash::MoreUtils