File Coverage

blib/lib/Sort/Hash.pm
Criterion Covered Total %
statement 74 76 97.3
branch 31 34 91.1
condition n/a
subroutine 10 10 100.0
pod 1 1 100.0
total 116 121 95.8


line stmt bran cond sub pod time code
1 1     1   30806 use strict;
  1         1  
  1         27  
2 1     1   4 use warnings FATAL => 'all';
  1         2  
  1         45  
3              
4             package Sort::Hash;
5             {
6             $Sort::Hash::VERSION = '2.05';
7             }
8 1     1   4 use Exporter 'import';
  1         2  
  1         28  
9 1     1   716 use Try::Tiny 0.13;
  1         1253  
  1         42  
10 1     1   5 use Scalar::Util 1.24;
  1         20  
  1         43  
11 1     1   12 use 5.008;
  1         3  
  1         518  
12              
13             our @EXPORT = qw( sort_hash ); # symbols to export on request
14              
15             # ABSTRACT: Sort the keys of a Hash into an Array.
16              
17             =pod
18              
19             =head1 NAME
20              
21             Sort::Hash - get the keys to a hashref sorted by their values.
22              
23             =head1 VERSION
24              
25             version 2.05
26              
27             =head1 SYNOPSIS
28              
29             Hash::Sort is a convenience for returning the keys of a hashref
30             sorted by their values. Numeric and alphanumeric sorting are supported,
31             the sort may be either Ascending or Descending.
32              
33             use Sort::Hash;
34             my @sorted = sort_hash( \%Hash );
35              
36             This does exactly the same as:
37              
38             my @sorted = ( sort { $Hash{$a} <=> $Hash{$b} } keys %Hash ) ;
39              
40             =head1 DESCRIPTION
41              
42             Get the keys to a hashref sorted by their values.
43              
44             =head1 Methods Exported
45              
46             =head2 sort_hash
47              
48             Return a sorted array containing the keys of a hash.
49              
50             =head3 Options to sort_hash
51              
52             nofatal warn and return an empty list instead of dying on
53             invalid sort (default behaviour)
54             silent like nofatal but doesn't emit warnings either
55             noempty if the hashref is empty treat it as an error
56             instead of returning an empty list ()
57             desc sort descending instead of ascending
58             asc ascending sort is the default but you can specify it
59             alpha sort alpha (treats numbers as text)
60             strictalpha sort alpha but refuse to sort numbers as text
61             numeric sort as numbers, default is numeric
62              
63             The arguments may be passed in any order.
64              
65             sort_hash( 'strictalpha', 'desc', $hashref );
66             sort_hash( $hashref, qw/ noempty nofatal alpha desc /);
67              
68             =head2 Errors
69              
70             Numeric sorts will fail if given a non-number. Normally alpha sorts will
71             treat numbers as text. strictalpha uses Scalar::Util::looks_like_number
72             to reject a hash that has any values that appear to be numbers.
73              
74             When the data is illegal for the sort type in effect, (only alpha has no restriction) sort_hash will die. If you prefer it not to, use nofatal to return () and warn instead of die, silent (implies nofatal) will just return () without a warning.
75              
76             Sorting an empty hashref will return nothing (). You can make this into an error that will die or warn depending on the nofatal flag with noempty.
77              
78             =head1 Changes from Version 1.x to 2.x
79              
80             The API has been changed from version 1. It is no longer possible to pass a naked hash, and it is no longer necessary to enter parameters as key value pairs. The default has also been changed from nofatal (warn only) to fatal (die on illegal sort).
81              
82             Upgrading to version 2. If you passed a naked hash just precede it with a backslash to pass it as a hashref. Add the parameter 'nofatal' to warn instead of die. Version 2 takes its arguments as an array and just ignores the extra arguments that would come in from a version 1 call. If you were already passing a hashref it will just work, except that illegal values are fatal without nofatal.
83              
84             =head2 If you need version1 compatibility
85              
86             Version 1 is included in the version 2 distribution, renamed as Sort::Hash1, just change your use statement to C.
87              
88             =cut
89              
90             sub sort_hash {
91 15     15 1 7840 my @sorted = ();
92             # my $H = shift;
93 15         28 my $H = {}; # $H must be a hashref, others are ints.
94 15         31 my ( $silent, $nofatal, $noempty, $desc, $alpha, $strictalpha ) = 0;
95 15         23 my ( $numeric, $asc ) = 1;
96 15         33 for (@_) {
97 32 100       79 if ( ref $_ eq 'HASH') { $H = $_ };
  15         24  
98 32 100       78 if ( $_ eq 'nofatal' ) { $nofatal = 1 }
  4         5  
99 32 100       70 if ( $_ eq 'silent' ) { $silent = 1; $nofatal = 1 }
  2         4  
  2         3  
100 32 100       64 if ( $_ eq 'noempty' ) { $noempty = 1 }
  1         2  
101 32 100       60 if ( $_ eq 'desc' ) { $desc = 1; $asc = 0 }
  1         2  
  1         3  
102 32 50       58 if ( $_ eq 'asc' ) { $asc = 1; $desc = 0 }
  0         0  
  0         0  
103 32 100       61 if ( $_ eq 'alpha' ) { $alpha = 1; $numeric = 0; }
  4         5  
  4         6  
104 32 100       61 if ( $_ eq 'strictalpha' ) {
105 1         4 $strictalpha = 1;
106 1         2 $alpha = 1;
107 1         2 $numeric = 0;
108             }
109 32 100       92 if ( $_ eq 'numeric' ) { $strictalpha = 0; $alpha = 0; $numeric = 1; }
  4         7  
  4         7  
  4         8  
110             }
111              
112             my $death = sub {
113 6 100   6   13 if ($nofatal) { warn $_[0] unless $silent; return (); }
  4 100       30  
  4         117  
114 2         24 else { die $_[0]; }
115 15         64 };
116             # $H initialized at 0, but if a hash was provided
117             #if( $H == 0 ) { die 'No Hash was provided for sorting.'}
118 15 100       32 if ($noempty) {
119 1 50       6 unless ( scalar( keys %$H ) ) {
120 1         23 $death->(
121             'Attempt to sort an empty hash while noempty is in effect');
122             }
123             }
124 14 100       36 if ($strictalpha) {
125 1         3 for ( values %{$H}) {
  1         4  
126 1 50       9 if ( Scalar::Util::looks_like_number($_) ) {
127 1         3 $death->(
128             'Attempt to Sort Numeric Value in Strict Alpha Sort');
129 1         8 return ;
130             }
131             }
132             }
133 13 100       25 if ($alpha) {
134 4         5 @sorted = ( sort { lc $H->{$a} cmp lc $H->{$b} } keys %{$H} );
  86         190  
  4         23  
135             }
136             else {
137             try {
138 9     9   481 @sorted = ( sort { $H->{$a} <=> $H->{$b} } keys %{$H} );
  74         160  
  9         51  
139             }
140             catch {
141 4     4   48 $death->('Attempt to Sort non-Numeric values in a Numeric Sort');
142 3         12 return ;
143             }
144 9         66 }
145 12 100       114 if ( $desc ) {
146 1         10 return reverse @sorted;
147             }
148 11         79 else { return @sorted; }
149             }
150              
151             =pod
152              
153             =head1 AUTHOR
154              
155             John Karr, C
156              
157             =head1 BUGS
158              
159             Please report any bugs or feature requests via the BitBucket issue tracker at
160             L. I will be
161             notified, and then you'll automatically be notified of progress on
162             your bug as I make changes.
163              
164             =head1 SUPPORT
165              
166             You can find documentation for this module with the perldoc command.
167              
168             You can also look for information at: The documentation for the
169             sort command in the Perl documentation.
170              
171             =head1 LICENSE AND COPYRIGHT
172              
173             Copyright 2014 John Karr.
174              
175             This program is free software; you can redistribute it and/or modify
176             it under the terms of the GNU General Public License as published by
177             the Free Software Foundation; version 3 or at your option
178             any later version.
179              
180             This program is distributed in the hope that it will be useful,
181             but WITHOUT ANY WARRANTY; without even the implied warranty of
182             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
183             GNU General Public License for more details.
184              
185             A copy of the GNU General Public License is available in the source tree;
186             if not, write to the Free Software Foundation, Inc.,
187             59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
188              
189             =cut
190              
191             1;