I'm lazy. So whenever I need to sort a hash, I don't want to have to think about the mechanics of sorting it...I just want it done.
I've been able to get away with just needing to sort one column/field in my hashes but recently needed to be able to sort on multiple columns so I modified my hash sorting subroutine to the below code after pilfering the idea (using "or" to string together multiple sort criterias) presented by lhoward in this node and after getting some great help at this node.
Hope this can help some other lazy monks.
mdog
$hash{'Me'}->{"name"} = "Me"; $hash{'Me'}->{"number"} = "7.7"; $hash{'Chuck'}->{"name"} = "Chuck"; $hash{'Chuck'}->{"number"} = "7.7"; $hash{'Zed'}->{"name"} = "Zed"; $hash{'Zed'}->{"number"} = "7.7"; $hash{'Wife'}->{"name"} = "Wife"; $hash{'Wife'}->{"number"} = "7.6"; $hash{'Dad'}->{"name"} = "Dad"; $hash{'Dad'}->{"number"} = "53"; $hash{'Michael'}->{"name"} = "Michael"; $hash{'Michael'}->{"number"} = "24"; my @sortedKeys = SortHashByMultipleColumns(\%hash,["number:asc","name: +asc"]); foreach my $sortedKey(@sortedKeys){ print $hash{$sortedKey}->{'number'} . " " . $hash{$sortedKey}->{'n +ame'} . "\n"; } sub SortHashByMultipleColumns{ my($hashRef,$sortInfoAR) = @_; my $sortCriteria; foreach my $sortInfo(@$sortInfoAR){ my($sortColumn,$sortDirection) = split(/\:/,$sortInfo); my $sortType; # VERIFY THAT THIS IS A VALID COLUMN if(! defined $hashRef->{((keys %$hashRef))[0]}->{$sortColumn}) +{ print "SortHashByMultipleColumns Error: $sortColumn is not + a column in this hash.\n"; exit(0); # VALID COLUMN, FIGURE OUT IF IT IS A NUMERIC COLUMN OR ALPHA } else { if($hashRef->{((keys %$hashRef))[0]}->{$sortColumn} =~ /^\ +d+/){ $sortType = "numeric"; } else { $sortType = "alpha"; } } # want to sort a number if($sortType eq "numeric"){ # sort it asc if($sortDirection =~ /asc/i){ # add an or if we already have something in the sort c +riteria if($sortCriteria){ $sortCriteria .= qq| or |; } $sortCriteria .= '$hashRef->{$a}->{\'' . $sortColumn . + '\'} <=> $hashRef->{$b}->{\'' . $sortColumn . '\'}'; # sort it desc } else { # add an or if we already have something in the sort c +riteria if($sortCriteria){ $sortCriteria .= qq| or |; } $sortCriteria .= '$hashRef->{$b}->{\'' . $sortColumn . + '\'} <=> $hashRef->{$a}->{\'' . $sortColumn . '\'}'; } # want to sort it by alpha } else { # sort it asc if($sortDirection =~ /asc/i){ # add an or if we already have something in the sort c +riteria if($sortCriteria){ $sortCriteria .= qq| or |; } $sortCriteria .= '$hashRef->{$a}->{\'' . $sortColumn . + '\'} cmp $hashRef->{$b}->{\'' . $sortColumn . '\'}'; # sort it desc } else { # add an or if we already have something in the sort c +riteria if($sortCriteria){ $sortCriteria .= qq| or |; } $sortCriteria .= '$hashRef->{$b}->{\'' . $sortColumn . + '\'} cmp $hashRef->{$a}->{\'' . $sortColumn . '\'}'; } } } my $sortfunc = eval "sub { $sortCriteria }"; my @sortedKeys = sort $sortfunc keys %$hashRef; return @sortedKeys; }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
•Re: Sort Multidimensional Hash By Multiple Columns
by merlyn (Sage) on Aug 06, 2004 at 19:18 UTC | |
by Limbic~Region (Chancellor) on Aug 06, 2004 at 19:51 UTC | |
by mdog (Pilgrim) on Aug 07, 2004 at 01:03 UTC |