in reply to •Re: Sort Multidimensional Hash By Multiple Columns
in thread Sort Multidimensional Hash By Multiple Columns

merlyn,
I am likely wrong, but I don't see mdog's code being a reinvention of Sort::Fields. The code is designed to arbitrarily sort the keys of a multi-dimensional hash based off user supplied key names. It also sorts ascending or descending based off user input and auto-magically detects numerical versus ASCIIBetical sorting.

What mdog has provided is not very flexible. It assumes a specific structure. I was going to try and make it more generic, but gave up after only duplicating the fuctionality. Why you might ask - besides getting bored, look at the atrocity:

#!/usr/bin/perl use strict; use Tie::Hash::Sorted; use Scalar::Util 'looks_like_number'; my @keys = qw(name number); tie my %hash, 'Tie::Hash::Sorted'; @{ $hash{$_} }{ @keys } = ($_, '7.7') for qw(Me Chuck Zed); @{ $hash{Wife} }{ @keys } = qw(Wife 7.6); @{ $hash{Dad} }{ @keys } = qw(Dad 53); @{ $hash{Michael} }{ @keys } = qw(Michael 24); sub Build_Sort { my $hash = shift; my (@col , @ord); $_ % 2 ? (push @ord , $_[$_]) : (push @col , $_[$_]) for 0 .. $#_; my $sort_it = sub { for ( 0 .. $#col ) { if ( $ord[$_] eq 'dsc' ) { if ( looks_like_number( $hash->{$a}{$col[$_]} ) && loo +ks_like_number( $hash->{$b}{$col[$_]} ) ) { next if ($hash->{$b}{$col[$_]} <=> $hash->{$a}{$co +l[$_]}) == 0; return $hash->{$b}{$col[$_]} <=> $hash->{$a}{$co +l[$_]}; } else { next if ($hash->{$b}{$col[$_]} cmp $hash->{$a}{$co +l[$_]}) == 0; return $hash->{$b}{$col[$_]} cmp $hash->{$a}{$co +l[$_]}; } } else { if ( looks_like_number( $hash->{$a}{$col[$_]} ) && loo +ks_like_number( $hash->{$b}{$col[$_]} ) ) { next if ($hash->{$a}{$col[$_]} <=> $hash->{$b}{$co +l[$_]}) == 0; return $hash->{$a}{$col[$_]} <=> $hash->{$b}{$co +l[$_]}; } else { next if ($hash->{$a}{$col[$_]} cmp $hash->{$b}{$co +l[$_]}) == 0; return $hash->{$a}{$col[$_]} cmp $hash->{$b}{$co +l[$_]}; } } } }; return sub { my $h = shift; [ sort $sort_it keys %$h ]; }; } tied( %hash )->Sort_Routine( Build_Sort(\%hash, number => 'dsc', name +=> 'asc') ); print "$hash{$_}{name}\t$hash{$_}{number}\n" for keys %hash;

Cheers - L~R

Replies are listed 'Best First'.
Re^3: Sort Multidimensional Hash By Multiple Columns
by mdog (Pilgrim) on Aug 07, 2004 at 01:03 UTC
    Yeah, it's not super portable but for my intents/purposes it works great and I don't have to install any modules to get it to do what I want.

    If anyone gets any value out of seeing the code (the "or" bit was new to me), then I'm happy. Just trying to give back a little to this great site!