# Sort keys in a hash numerically

M

#### mickey

Hi,

I have a has with keys like
Char. 123
Char. 721
Char. 234

and so on, that is a char followed by an integer.

I want to iterate over the whole hash in numerical order. At present using

foreach my \$key(sort (keys %char))

sorts them but in lexicographic order. Is there a way in Perl around that?

Thanks,
-M

X

#### xhoster

mickey said:
Hi,

I have a has with keys like
Char. 123
Char. 721
Char. 234

and so on, that is a char followed by an integer.

If all the keys start with "Char. ", that seems pretty uninteresting.
Why not just strip that off and store only the number?
I want to iterate over the whole hash in numerical order. At present
using

foreach my \$key(sort (keys %char))

foreach my \$key (sort {sfrn(\$a) <=> sfrn(\$b)} keys %char)

where sfrn is Some Function that takes a key and Returns the Numberic
portion.

Xho

U

#### usenet

mickey said:
sorts them but in lexicographic order. Is there a way in Perl around that?

perldoc -q sort

How do I sort an array by (anything)?

X

#### Xicheng Jia

mickey said:
Hi,

I have a has with keys like
Char. 123
Char. 721
Char. 234

and so on, that is a char followed by an integer.

I want to iterate over the whole hash in numerical order. At present using

foreach my \$key(sort (keys %char))

sorts them but in lexicographic order. Is there a way in Perl around that?

A solution with the Schwartzian Transform:

my %hash = (
"Char.123" => "part1",
"Char.721" => "part2",
"Char.234" => "part3",
);

print map { "\$_-> => \$hash{\$_->}\n" }
sort { \$a-> <=> \$b-> }
map { [ \$_, [ split/\./ ] ] }
keys %hash;

Xicheng

M

#### mickey

If all the keys start with "Char. ", that seems pretty uninteresting.
Why not just strip that off and store only the number?

Thanks everyone. I just stripped off the chars which made everything
simpler.

-M

A

#### anno4000

Xicheng Jia said:
mickey said:
Hi,

I have a has with keys like
Char. 123
Char. 721
Char. 234

and so on, that is a char followed by an integer.

I want to iterate over the whole hash in numerical order. At present using

foreach my \$key(sort (keys %char))

sorts them but in lexicographic order. Is there a way in Perl around that?

A solution with the Schwartzian Transform:

my %hash = (
"Char.123" => "part1",
"Char.721" => "part2",
"Char.234" => "part3",
);

print map { "\$_-> => \$hash{\$_->}\n" }
sort { \$a-> <=> \$b-> }
map { [ \$_, [ split/\./ ] ] }
keys %hash;

A regex capture instead of split is a little simpler:

print map { "\$_-> => \$hash{\$_->}\n" }
sort { \$a-> <=> \$b-> }
map { [ \$_, /(\d+)/ ] }
keys %hash;

Anno