[Koha-patches] [PATCH] Add undef-tolerant and number-respecting sort function.

Joe Atzberger joe.atzberger at liblime.com
Thu Dec 18 04:36:06 CET 2008


---
 C4/Reports.pm |  113 +++++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 90 insertions(+), 23 deletions(-)

diff --git a/C4/Reports.pm b/C4/Reports.pm
index d0bbe70..ce73f71 100644
--- a/C4/Reports.pm
+++ b/C4/Reports.pm
@@ -18,12 +18,12 @@ package C4::Reports;
 # Suite 330, Boston, MA  02111-1307 USA
 
 use strict;
+use warnings;
 use CGI;
 
 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
 use C4::Context;
 use C4::Debug;
-# use Smart::Comments;
 # use Data::Dumper;
 
 BEGIN {
@@ -33,31 +33,10 @@ BEGIN {
     @ISA = qw(Exporter);
     @EXPORT = qw(
         GetDelimiterChoices
+        NumberOrStringSort
     );
 }
 
-=head1 NAME
-   
-C4::Reports - Module for generating reports 
-
-=head1 DESCRIPTION
-
-This module contains functions common to reports.
-
-=head1 EXPORTED FUNCTIONS
-
-=head2 GetDelimiterChoices
-
-=over 4
-
-my $delims = GetDelimiterChoices;
-
-=back
-
-This will return a list of all the available delimiters.
-
-=cut
-
 sub GetDelimiterChoices {
     my $dbh = C4::Context->dbh;
 
@@ -81,10 +60,98 @@ sub GetDelimiterChoices {
                 -multiple => 0 );
 }
 
+sub NumberOrStringSort {
+    my $a = shift;
+    my $b = shift;
+    # first we need to bail out if either element is undef
+    # print STDERR sprintf "sorting %5s vs. %5s\n", (defined($a) ? $a : "UNDEF"), (defined($b) ? $b : "UNDEF");
+    defined($a) or return (defined($b) ? -1 : 0);
+    defined($b) or return 1;
+    ($a =~ /^\-?\d+$/ and $b =~ /^\-?\d+$/) and return $a <=> $b;
+        # so if both elements look like numbers, sort them numerically
+    return $a cmp $b;   # else revert to string sort order
+}
+
 1;
 
 __END__
 
+=head1 NAME
+   
+C4::Reports - Module for generating reports 
+
+=head1 DESCRIPTION
+
+This module contains functions common to reports.
+
+=head1 EXPORTED FUNCTIONS
+
+=head2 GetDelimiterChoices
+
+=over 4
+
+my $delims = GetDelimiterChoices;
+
+=back
+
+This will return a list of all the available delimiters.
+
+=head2 NumberOrStringSort
+
+=over 4
+
+my @array = sort {NumberOrStringSort($a,$b)} @array;
+
+=back
+
+Used to compel sort order that respects numbers.  That is, it doesn't sort 11 ahead of 2.  All numbers will sort out
+to an earlier group before non-numerical strings.  It can also handle undefined elements. 
+
+Test it with:
+perl -we 'use C4::Reports;
+    my @x=(3,12,2,undef,,114,1,-1,-20,"foo",14,"bar",101,undef);
+    print "\n", scalar(@x), " elements:\n",
+    map {defined($_) ? "$_\n" : "UNDEF\n"}
+    sort {NumberOrStringSort($a,$b)} @x;'
+
+The output should look like:
+    13 elements:
+    UNDEF
+    UNDEF
+    -20
+    -1
+    1
+    2
+    3
+    12
+    14
+    101
+    114
+    bar
+    foo
+
+Comparing this to the output of regular sort, you would first get 9 warnings like:
+    Use of uninitialized value in sort at -e line 1.
+
+Then the output would be:
+    13 elements:
+    UNDEF
+    UNDEF
+    -1
+    -20
+    1
+    101
+    114
+    12
+    14
+    2
+    3
+    bar
+    foo
+
+NumberOrStringSort is not really specific to Reports, so it is conceivable it should
+move to a broader Utility class.  
+
 =head1 AUTHOR
 
 Jesse Weaver <jesse.weaver at liblime.com>
-- 
1.5.5.GIT




More information about the Koha-patches mailing list