same applies here again. this is the trick used:
we dig out that value we want to sort on, make that the key of our hash and
go from there
let me adres the @arr you presented.
### EXAMPLE 1 ###
### this will NOT eliminate the value we're sorting on from the list ###
while ( my @s = splice(@arr,0,4) ) { $hash{$s[2]} = \@s }
for (sort keys %hash) {print "$_ is @{$hash{$_}}\n"}
this will print:
3 is 1 2 3 4
6 is 4 5 6 7
7 is 5 6 7 8
8 is 3 1 8 3
### EXAMPLE 2 ###
### this WILL eliminate the value we're sorting on from the list ###
while ( my @s = splice(@arr,0,4) ) { $hash{splice(@s,2,1)} = \@s }
for (sort keys %hash) {print "$_ is @{$hash{$_}}\n"}
this will print:
3 is 1 2 4
6 is 4 5 7
7 is 5 6 8
8 is 3 1 3
Ok, now for some explenation.
the " while ( ) " part is the same in both cases, here's what it does:
while splicing @arr in parts of 4 (like you indicated with your colums in
@arr) we store those 4 values in @s and we'll do some operations. once @arr
has no values anymore, the while loop will exit.
in essence, it's the same as saying:
for(1..4) {
my $foo = shift @arr;
push @s, $foo;
}
a short word on 'splice':
as we use it here, it works as follows;
take out of array @arr the values, starting at position 0 and the next 4
from there (giving you 1 2 3 4 first time thru the loop)
splice will return the LAST element spliced off in scalar context (ie, if we
had said "my $s" instead of "my @s" ), wheras it will return ALL spliced off
elements in list context (what we use here; @s)
ok, on with the interesting code. first i'll cover what happens in example
1:
$hash{$s[2]} = \@s
that means the key of %hash will be the 3rd element of @s, whereas it's
value will be a reference to @s
(if this confuses you, read the reference tutorial on
www.sharemation.com/~perl/tut )
in example 2, we eliminate the value we'll use as key from the array we'll
store as the key's value (yes, read that agian =)
for that, we use another splice:
$hash{splice(@s,2,1)} = \@s
splice wll return the *last* value it spliced out of the array (in thise we
do only one, as you can see by the '1' in the splice command) and sets that
as the key of the hash... the value corresponding to the key will be a
reference to what is left of @s
( which is everything, minus the key we extracted)
now for the print statement, this might appear a bit funky on first glance,
but it's not so bad, i promiss ;-)
for (sort keys %hash) {print "$_ is @{$hash{$_}}\n"}
just like in previous mail with the map function, we use the 'sort keys
%hash' bit again... but this time there's an oddity in the print statement;
print "$_ is @{$hash{$_}}\n"
@{$hash{$_}} is basicly the dereferencing of the array referred to by the
key of the hash{$_}. so as you saw we put \@s in the hash, to get a normal
array out, we need to say @{$reference_to_array} and that's just what we're
doing here
again, if this confuses you, read the reference tutorial on
www.sharemation.com/~perl/tut
hope this clears things up,
Jos Boumans
> Thnaks a lot Jos. The idea of reading the array into a hash is quite
appealing, and
> simple too. But I have a small problem with this:
>
> What if I want to sort on the second column of the array? Or if there are
more
> than two columns?
>
> Say we have:
> my @arr = qw(
> 1 2 3 4
> 4 5 6 7
> 5 6 7 8
> 1 2 3 4
> 3 1 8 3
> );
> And if I wanted to sort on the 3rd column.
> Then I could write:
>
> @sorted = sort { $a->[2] <=> $b->[2] } @arr;
>
> # or 'cmp' if the sorting is to be lexical.