Sorting a Hash of Arrays by an Element in the Array

A

Alf McLaughlin

Hello all-
I have seen many old questions where people ask if this can be done,
and many responses where people claim it is not possible. However, I
believe I have done it successfully and that it is quite easy:

for my $key (sort {$hash{$a}->[0] <=> $hash{$b}->[0]} keys %hash) {
print "$key\n";
}

Am I missing something??? It looks as if it can be done to me.

Thanks,
Alf
 
U

usenet

Alf said:
for my $key (sort {$hash{$a}->[0] <=> $hash{$b}->[0]} keys %hash) {
print "$key\n";
}
Am I missing something??? It looks as if it can be done to me.

I dunno. Run this program and tell me what you are trying to say:

#!/usr/bin/perl
use strict; use warnings;
use Data::Dumper;

my %hash = (col=>[qw/red yellow green/],
make=>[qw/ford chevy/],body=>[qw/coupe sedan/]);

print Dumper (\%hash); #verify the data structure

for my $key (sort {$hash{$a}->[0] cmp $hash{$b}->[0]} keys %hash) {
print "$key\n";
}

__END__
 
A

Alf McLaughlin

I am trying to say you will see the keys printed in the order the 1st
element of the array will be sorted in. I tried this and it worked for
me:

body (coupe is the earliest in the alphabet)
make (ford is the middle)
col (red is the last in the alphabet)

when I changed the first values of the array and played with it, it
always seemed to sort correctly. Actually, this surprised me because I
only expected numbers to sort correctly. I think it may not be sorting
the words correctly, but I'm sure it works for numbers.

Alf said:
for my $key (sort {$hash{$a}->[0] <=> $hash{$b}->[0]} keys %hash) {
print "$key\n";
}
Am I missing something??? It looks as if it can be done to me.

I dunno. Run this program and tell me what you are trying to say:

#!/usr/bin/perl
use strict; use warnings;
use Data::Dumper;

my %hash = (col=>[qw/red yellow green/],
make=>[qw/ford chevy/],body=>[qw/coupe sedan/]);

print Dumper (\%hash); #verify the data structure

for my $key (sort {$hash{$a}->[0] cmp $hash{$b}->[0]} keys %hash) {
print "$key\n";
}

__END__
 
P

Paul Lalli

Alf McLaughlin wrote:

Alf,

Please learn to quote properly. Post your reply *below* the quoted
text, after trimming it down to the relevant bits. Thank you.

[quoting fixed below]
Alf McLaughlin wrote: [Subject: Sorting a Hash of Arrays by an Element in the Array]
for my $key (sort {$hash{$a}->[0] <=> $hash{$b}->[0]} keys %hash) {
print "$key\n";
}
Am I missing something??? It looks as if it can be done to me.

I dunno. Run this program and tell me what you are trying to say:

#!/usr/bin/perl
use strict; use warnings;

my %hash = (col=>[qw/red yellow green/],
make=>[qw/ford chevy/],body=>[qw/coupe sedan/]);

for my $key (sort {$hash{$a}->[0] cmp $hash{$b}->[0]} keys %hash) {
print "$key\n";
}

__END__
I am trying to say you will see the keys printed in the order the 1st
element of the array will be sorted in. I tried this and it worked for
me:

body (coupe is the earliest in the alphabet)
make (ford is the middle)
col (red is the last in the alphabet)

Okay, so obviously that *does* work. So what are you getting at?
Where are these "old questions" you claim to have seen that gave an
incorrect answer? Are you sure they're asking the same thing you're
asking? Give us a point of reference.
Actually, this surprised me because I
only expected numbers to sort correctly.

Your example would only sort numbers correctly. David's would only
I think it may not be sorting
the words correctly, but I'm sure it works for numbers.

Now you've completely lost me. You saw David's example, verified that
it worked, but suddenly you're not sure if it sorted the words
correctly?

Paul Lalli
 
U

usenet

Alf said:
I tried this and it worked for me:

body (coupe is the earliest in the alphabet)
make (ford is the middle)
col (red is the last in the alphabet)

But "chevy" (make) comes before "coupe" (body).
 
A

Alf McLaughlin

Paul said:
Alf McLaughlin wrote:

Alf,

Please learn to quote properly. Post your reply *below* the quoted
text, after trimming it down to the relevant bits. Thank you.

[quoting fixed below]
Alf McLaughlin wrote: [Subject: Sorting a Hash of Arrays by an Element in the Array]
for my $key (sort {$hash{$a}->[0] <=> $hash{$b}->[0]} keys %hash) {
print "$key\n";
}
Am I missing something??? It looks as if it can be done to me.

I dunno. Run this program and tell me what you are trying to say:

#!/usr/bin/perl
use strict; use warnings;

my %hash = (col=>[qw/red yellow green/],
make=>[qw/ford chevy/],body=>[qw/coupe sedan/]);

for my $key (sort {$hash{$a}->[0] cmp $hash{$b}->[0]} keys %hash) {
print "$key\n";
}

__END__
I am trying to say you will see the keys printed in the order the 1st
element of the array will be sorted in. I tried this and it worked for
me:

body (coupe is the earliest in the alphabet)
make (ford is the middle)
col (red is the last in the alphabet)

Okay, so obviously that *does* work. So what are you getting at?
Where are these "old questions" you claim to have seen that gave an
incorrect answer? Are you sure they're asking the same thing you're
asking? Give us a point of reference.
Actually, this surprised me because I
only expected numbers to sort correctly.

Your example would only sort numbers correctly. David's would only
I think it may not be sorting
the words correctly, but I'm sure it works for numbers.

Now you've completely lost me. You saw David's example, verified that
it worked, but suddenly you're not sure if it sorted the words
correctly?

Paul Lalli

Apologies for the misquoting. This better?

Ah, I've lost you due to my own ignorance. I did not catch that he
changed "<=>" to "cmp"; sorry for the confusion.

I do not have time to dig up old questions for you, but I casually
noticed that some people like to answer this question as "this cannot
be done because you cannot guarantee keys in a hash are stored in a
sorted manner... etc etc". Well, I know that and it's good to know,
but since you can always sort a hash who really cares? The point of me
asking this is actually simple: Can I be guranteed that sorting a Hash
of Arrays like this (on an array element) will always work? That's
really my question. Again, my apologies (this posting has gotten a lot
more apologetic than I had originally intended- from now on I apologize
for nothing in this post! So there.)

But, I have a new question now that is a logical extension of this.
Suppose I have a Hash of a Hash of arrays. Is there a way to sort this
by an element in the array? I know I can write my own subroutine to
create a new hash and sort it that way (or whatever- MTOWTDI), but I
was just curious.

Thanks,
Alf
 
P

Paul Lalli

Alf said:
Apologies for the misquoting. This better?

Better, yes. Best would be to quote only what is relevant to your
reply. For example, your line above could have come right after my
request that you quote properly. Basically, your quoting should enable
anyone reading just this message to understand what's going on without
having to keep scrolling up or down, or looking at any other message.
I do not have time to dig up old questions for you, but I casually
noticed that some people like to answer this question as "this cannot
be done because you cannot guarantee keys in a hash are stored in a
sorted manner... etc etc".

I'm afraid I simply fail to believe you. I am far more inclined to
believe that there is a difference between the questions you are
referring to, and the question you actually asked. Yes, what you asked
is obviously very possible. It is entirely likely that another post
was asking a similar, but different enough, question.
The point of me
asking this is actually simple: Can I be guranteed that sorting a Hash
of Arrays like this (on an array element) will always work? That's
really my question.

I don't really get what you mean by this question. If you have a hash
of arrays, can you always obtain a list of keys of that hash, sorted by
the X'th element of the 'inner' arrays of the hash? Yes.
But, I have a new question now that is a logical extension of this.
Suppose I have a Hash of a Hash of arrays. Is there a way to sort this
by an element in the array?

First: You need to use better terminology. There is no such thing as
sorting a hash. What you can do is obtain a list of keys of that hash,
and sort that list of keys. You can then operate on a sorted list of
keys. The hash itself, however, cannot be sorted.

Second: Yes, of course you can. Using the same technique you already
demonstrated, but with one extra dimension:

my @sorted_keys = sort { $a->{key}[0] cmp $b->{key}[0] } %big_hash;

This will obtain a list of all of %big_hash's keys, sorted by the order
of the first element of the array referenced by the value of the hash
at the key 'key'.

Paul Lalli
 
E

Eden Cardim

I do not have time to dig up old questions for you, but I casually
noticed that some people like to answer this question as "this cannot
be done because you cannot guarantee keys in a hash are stored in a
sorted manner... etc etc".

You're missing the point, there's quite a big difference between
"sorting" and "ordering". Hashes aren't ordered in any way because of
the nature of the algorithmic procedure behind their building process.
You can, however, sort the keys, or values, or both in a particular
manner, if you'd like.
Well, I know that and it's good to know, but since you can always sort a hash who really cares?

Wrong, this is VERY relevant, since hashes aren't ordered, they can't
remember the order in which the elements were stored in them. If you
use a hash-based data-structure to store, say, an XML document, you
won't be able to do round-tripping. If your XML happens to be an HTML
document, everyone will care when you render your page ad hoc.
 
A

Alf McLaughlin

Geez, sorry I didn't ask my question like you would of; I guess you
rule. Anyway, thanks for the info.
 
J

Jürgen Exner

Alf said:
I do not have time to dig up old questions for you, but I casually
noticed that some people like to answer this question as "this cannot
be done because you cannot guarantee keys in a hash are stored in a
sorted manner... etc etc". Well, I know that and it's good to know,
but since you can always sort a hash who really cares?

Well, apparently you did not understand then. A hash does not have any
sequence or order. Sorting something is basically ensuring that for each
element the next element is larger than the previous element (assuming
ascending sort). Now, how do you sort a data structure that does not have a
concept of "next" or "previous" to begin with? Asking for sorting a hash is
as meaningful as asking for sorting a mathematical set.
So no, you cannot sort a hash.

Of course you can extract the keys of hash and sort them into a list/array
or extract the values of a hash and sort them into a list/array. That is
really old. But then you have a sorted list/array, not a sorted hash.
The point of
me asking this is actually simple: Can I be guranteed that sorting a
Hash of Arrays like this (on an array element) will always work?

I have no idea what "sorting a HoA on an array element" is supposed to mean.
- sorting a hash is meaningless
- assuming you are sorting the values and those values happen to be arrays
then I still don't understand what you mean by "on an array element"

jue
 
A

Alf McLaughlin

I know the hash doesn't literally exist as a sorted data structure. I
was speaking specifically of using the sort function on the keys. But,
instead of the keys being sorted I want to see every possible
$hash{$key} value sorted by which every element of \@array that I
choose. The question has been officially answered. For those who wish
to attack the semantics of the question, I feel sorry that you don't
have better things to do with your time.
 
T

Tad McClellan

Alf McLaughlin said:
For those who wish
to attack the semantics of the question,


The meaning of a question is quite central to getting an answer
to the question!

I feel sorry that you don't
have better things to do with your time.


Thanks for identifying yourself.

Now I can do better things with my time.
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I know the hash doesn't literally exist as a sorted data structure. I
was speaking specifically of using the sort function on the keys.

The set of keys of a hash is not a hash; it is a list. Of course a
list may be sorted.

[...]
For those who wish
to attack the semantics of the question, I feel sorry that you don't
have better things to do with your time.

Do try to learn the difference between "asking for clarity" and
"attacking". You claimed:
It looks as if [sorting a hash] can be done to me.

Now that people have delved further into your statement, it turns out
that what you meant is that the keys can be sorted. That's fine. I
feel sorry that you think that the process of discovering what you
were truly asserting is a waste of time.

- --
Eric
`$=`;$_=\%!;($_)=/(.)/;$==++$|;($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,@%)=(
$!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++;
$_++;$_++;($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&$~,$#,);$,++
;$,++;$^|=$";`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&$=`
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (MingW32) - WinPT 0.7.96rc1

iD8DBQFDfyg2Y96i4h5M0egRAp5XAJ4hKaCa5qd8MsTpGriFJfHddD0zlwCfUJX3
Pco/zo29z9l1fGiGyCZ8jdU=
=ep0b
-----END PGP SIGNATURE-----
 
R

robic0

On 17 Nov 2005 12:22:30 -0800, "Alf McLaughlin" <[email protected]>
wrote:
Hey alf,
I just briefly read your initial post and a couple more responses.
Didn't read all the responses because I didn't want to read all
the "read this rule" or "perldoc this" or "off the wall" stuff
embedded in most of these regulars' reply's, so I
[skip meaningless 1-liners entirely].

To your question, it is absolutely possible to sort anything
with respect to anything. However its only meaningfull when
you do something with the data at the same level of the sort.
You can't go 3 levels of hashes/hashes/refs in then print anything
meaningfull with respect to the outer level container.
You get what I mean bro?
Paul said:
Alf McLaughlin wrote:

Alf,

Please learn to quote properly. Post your reply *below* the quoted
text, after trimming it down to the relevant bits. Thank you.

[quoting fixed below]
(e-mail address removed) wrote:
Alf McLaughlin wrote:
[Subject: Sorting a Hash of Arrays by an Element in the Array]
for my $key (sort {$hash{$a}->[0] <=> $hash{$b}->[0]} keys %hash) {
print "$key\n";
}
Am I missing something??? It looks as if it can be done to me.

I dunno. Run this program and tell me what you are trying to say:

#!/usr/bin/perl
use strict; use warnings;

my %hash = (col=>[qw/red yellow green/],
make=>[qw/ford chevy/],body=>[qw/coupe sedan/]);

for my $key (sort {$hash{$a}->[0] cmp $hash{$b}->[0]} keys %hash) {
print "$key\n";
}

__END__
I am trying to say you will see the keys printed in the order the 1st
element of the array will be sorted in. I tried this and it worked for
me:

body (coupe is the earliest in the alphabet)
make (ford is the middle)
col (red is the last in the alphabet)

Okay, so obviously that *does* work. So what are you getting at?
Where are these "old questions" you claim to have seen that gave an
incorrect answer? Are you sure they're asking the same thing you're
asking? Give us a point of reference.
Actually, this surprised me because I
only expected numbers to sort correctly.

Your example would only sort numbers correctly. David's would only
I think it may not be sorting
the words correctly, but I'm sure it works for numbers.

Now you've completely lost me. You saw David's example, verified that
it worked, but suddenly you're not sure if it sorted the words
correctly?

Paul Lalli

Apologies for the misquoting. This better?

Ah, I've lost you due to my own ignorance. I did not catch that he
changed "<=>" to "cmp"; sorry for the confusion.

I do not have time to dig up old questions for you, but I casually
noticed that some people like to answer this question as "this cannot
be done because you cannot guarantee keys in a hash are stored in a
sorted manner... etc etc". Well, I know that and it's good to know,
but since you can always sort a hash who really cares? The point of me
asking this is actually simple: Can I be guranteed that sorting a Hash
of Arrays like this (on an array element) will always work? That's
really my question. Again, my apologies (this posting has gotten a lot
more apologetic than I had originally intended- from now on I apologize
for nothing in this post! So there.)

But, I have a new question now that is a logical extension of this.
Suppose I have a Hash of a Hash of arrays. Is there a way to sort this
by an element in the array? I know I can write my own subroutine to
create a new hash and sort it that way (or whatever- MTOWTDI), but I
was just curious.

Thanks,
Alf
 
R

robic0

On 17 Nov 2005 12:22:30 -0800, "Alf McLaughlin" <[email protected]>
wrote:
Hey alf,
I just briefly read your initial post and a couple more responses.
Didn't read all the responses because I didn't want to read all
the "read this rule" or "perldoc this" or "off the wall" stuff
embedded in most of these regulars' reply's, so I
[skip meaningless 1-liners entirely].

To your question, it is absolutely possible to sort anything
with respect to anything. However its only meaningfull when
you do something with the data at the same level of the sort.
You can't go 3 levels of hashes/hashes/refs in then print anything
meaningfull with respect to the outer level container.
You get what I mean bro?

In other words, you have sorted a "outer container" of references.
The outer data has nothing to do with the object of the sort,
which is the inner. Its only meaningfull when you act on that order
at the level of the sort of intention. And to add to that. As a
systematic programming construct, all the layers have to be homogenous
down to the object sort (if you know what I mean bro?).
Paul said:
Alf McLaughlin wrote:

Alf,

Please learn to quote properly. Post your reply *below* the quoted
text, after trimming it down to the relevant bits. Thank you.

[quoting fixed below]

(e-mail address removed) wrote:
Alf McLaughlin wrote:
[Subject: Sorting a Hash of Arrays by an Element in the Array]
for my $key (sort {$hash{$a}->[0] <=> $hash{$b}->[0]} keys %hash) {
print "$key\n";
}
Am I missing something??? It looks as if it can be done to me.

I dunno. Run this program and tell me what you are trying to say:

#!/usr/bin/perl
use strict; use warnings;

my %hash = (col=>[qw/red yellow green/],
make=>[qw/ford chevy/],body=>[qw/coupe sedan/]);

for my $key (sort {$hash{$a}->[0] cmp $hash{$b}->[0]} keys %hash) {
print "$key\n";
}

__END__
I am trying to say you will see the keys printed in the order the 1st
element of the array will be sorted in. I tried this and it worked for
me:

body (coupe is the earliest in the alphabet)
make (ford is the middle)
col (red is the last in the alphabet)

Okay, so obviously that *does* work. So what are you getting at?
Where are these "old questions" you claim to have seen that gave an
incorrect answer? Are you sure they're asking the same thing you're
asking? Give us a point of reference.

Actually, this surprised me because I
only expected numbers to sort correctly.

Your example would only sort numbers correctly. David's would only
sort strings correctly. They are not the same. Yours used the <=>
operator, while David's used the cmp operator.

I think it may not be sorting
the words correctly, but I'm sure it works for numbers.

Now you've completely lost me. You saw David's example, verified that
it worked, but suddenly you're not sure if it sorted the words
correctly?

Paul Lalli

Apologies for the misquoting. This better?

Ah, I've lost you due to my own ignorance. I did not catch that he
changed "<=>" to "cmp"; sorry for the confusion.

I do not have time to dig up old questions for you, but I casually
noticed that some people like to answer this question as "this cannot
be done because you cannot guarantee keys in a hash are stored in a
sorted manner... etc etc". Well, I know that and it's good to know,
but since you can always sort a hash who really cares? The point of me
asking this is actually simple: Can I be guranteed that sorting a Hash
of Arrays like this (on an array element) will always work? That's
really my question. Again, my apologies (this posting has gotten a lot
more apologetic than I had originally intended- from now on I apologize
for nothing in this post! So there.)

But, I have a new question now that is a logical extension of this.
Suppose I have a Hash of a Hash of arrays. Is there a way to sort this
by an element in the array? I know I can write my own subroutine to
create a new hash and sort it that way (or whatever- MTOWTDI), but I
was just curious.

Thanks,
Alf
 
R

robic0

ehT gninaem fo a noitseuq si etiuq lartnec ot gnitteg na rewsna
ot eht noitseuq!




sknahT rof gniyfitnedi flesruoy.

woN I nac od retteb sgniht htiw ym emit.
huh?
Tad you need a cat scan...
 
R

robic0

Hello all-
I have seen many old questions where people ask if this can be done,
and many responses where people claim it is not possible. However, I
believe I have done it successfully and that it is quite easy:

for my $key (sort {$hash{$a}->[0] <=> $hash{$b}->[0]} keys %hash) {
print "$key\n";
}

Am I missing something??? It looks as if it can be done to me.

Thanks,
Alf

Alf, its my experience that the regular posters that responded to
yo can't think past level 1 sort. You didn't waste your time though
I just postedted a few days late.
Feel free to post more questions like this, it drives the regular
1-liner brigade nuts..
-Good job!!!
 
L

l v

Alf said:
noticed that some people like to answer this question as "this cannot
be done because you cannot guarantee keys in a hash are stored in a
sorted manner... etc etc".
Thanks,
Alf

I thought it was: you can not retrieve the keys of a hash in the order
they were inserted due to the way they are stored.

Len
 
R

robic0

On 17 Nov 2005 12:22:30 -0800, "Alf McLaughlin" <[email protected]>
wrote:
Hey alf,
I just briefly read your initial post and a couple more responses.
Didn't read all the responses because I didn't want to read all
the "read this rule" or "perldoc this" or "off the wall" stuff
embedded in most of these regulars' reply's, so I
[skip meaningless 1-liners entirely].

To your question, it is absolutely possible to sort anything
with respect to anything. However its only meaningfull when
you do something with the data at the same level of the sort.
You can't go 3 levels of hashes/hashes/refs in then print anything
meaningfull with respect to the outer level container.
You get what I mean bro?
What I mean is that the inner sort level meaning must be
reflected in the way you present or hold that information.
For example, an embedded inner structure contains the
dates of vacinations. The container now is in relation
to that so any knowledge of that order is only relative
to those inner dates. You know what I mean.....
 

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,982
Messages
2,570,186
Members
46,744
Latest member
CortneyMcK

Latest Threads

Top