sort on multiple hash values

Z

Zhiliang Hu

I have a hash with multiple values, like in:

Marty => 32877::2
Bart => 14857::2
Torq => 65221::1
etc

and I wish to sort on. say, first field of the hash value:

foreach $key (sort mysort keys %hasha ) { ... }

sub mysort {
map { $_->[0] }
sort { $a->[0] cmp $b->[0] }
map { [ $_, split(/::/,[0] ] }
}

but confused as how to 'map' the elements... need help -- Thanks in
advance!
 
J

Jürgen Exner

Zhiliang Hu said:
I have a hash with multiple values, like in:

Marty => 32877::2
Bart => 14857::2
Torq => 65221::1
etc

and I wish to sort on. say, first field of the hash value:

You don't because hashes by definition do not have a sequence and
therefore cannot be sorted.

What _do_ you want to sort? An array of the keys of the hash? An arrray
of the values of the hash? Something totally different?

See also the FAQ: "How do I sort a hash[...]?"

jue
 
J

John W. Krahn

Zhiliang said:
I have a hash with multiple values, like in:

Marty => 32877::2
Bart => 14857::2
Torq => 65221::1
etc

and I wish to sort on. say, first field of the hash value:

Have you thought about using a Hash of Arrays instead?

my %hasha = (
Marty => [ 32877, 2 ],
Bart => [ 14857, 2 ],
Torq => [ 65221, 1 ],
);

foreach $key (sort mysort keys %hasha ) { ... }

Why are you are supplying sort with a subroutine that has sort in it?
Did you want to sort on the keys as well as the values?

foreach my $key ( mysort keys %hasha ) { ... }

sub mysort {
map { $_->[0] }
sort { $a->[0] cmp $b->[0] }
map { [ $_, split(/::/,[0] ] }

You are supplying split() with an anonymous array which translates to a
number that has no ':' characters in it. The mysort subroutine is
passed a list of keys from the %hasha hash in the @_ array but you are
not accessing that list, but even if you were, to get the value from
that key you need to get it from the hash as $hasha{$_}. You are
comparing what would be the keys of the hash but you said you wanted to
compare the values.

}

but confused as how to 'map' the elements... need help -- Thanks in
advance!

sub mysort {
map $_->[ 0 ],
sort { $a->[ 1 ] <=> $b->[ 1 ] }
map [ $_, ( split /::/, $hasha{ $_ } )[ 0 ] ],
@_
}



John
 
Z

Zhiliang Hu

Sorry I must be in day-dreaming for these errors.
Any way I changed my approach to have solved the problem. John's
suggestion to use a hash of arrays is a good idea for the problem
though (another evidence to see multiple ways to accomplish
something!)

Thanks for all the replies.

Zhiliang
 
P

Peter J. Holzer

You don't because hashes by definition do not have a sequence and
therefore cannot be sorted.

Jürgen, can you please try to be little less literal? I see no
indication that the OP wanted to create a hash with an intrinsic sort
order.

What _do_ you want to sort? An array of the keys of the hash? An arrray
of the values of the hash?

One of those two, almost certainly. It doesn't really matter, since the
technique is the same, you just write

sort { cmp_func($hash{$a}, $hash{$b}) } keys %hash
in one case and
sort { cmp_func($a, $b) } values %hash
in the other (the OP already stated that the sort order depends only on
the value, not the key).

Something totally different?
Unlikely.


See also the FAQ: "How do I sort a hash[...]?"

I don't see you berating Brian that he can't sort a hash ...

hp
 
J

Jürgen Exner

Peter J. Holzer said:
Jürgen, can you please try to be little less literal? I see no
indication that the OP wanted to create a hash with an intrinsic sort
order.

I guess that's my pet peeve. If people would stop talking about sorting
a hash and instead spend just a minute thinking about what they _REALLY_
want to do, then the solution would be obvious, please see below.

[...]
sort { cmp_func($hash{$a}, $hash{$b}) } keys %hash

This is I want to sort the keys of the hash by their associated values,
using some criteria.
in one case and
sort { cmp_func($a, $b) } values %hash

And this is I want to sort the values of the hash by their own values,
using some criteria.

Both follow the standard pattern "I want to sort X by criteria Y". The
solution will jump right at you once you recognize that sort() takes two
parameters: the compare function and the list(!) of data to be sorted.
So first get that list (no, it is not the hash!), and then based on the
elements in that list define your compare function.

Once you forget the idea about sorting a hash and realize that actually
you are sorting a list and that you have to create that list first, then
the problem looses the 'rocket science complexity' and becomes trivial.

Unfortunately most people keep insisting on thinking in terms of sorting
a hash.... :-((

jue
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top