Andreas
Andreas

Reputation: 1261

Sorting alphanumeric hash keys in Perl?

Given the following hash:

%errors = (
    "2013-W9 -> 2013-W12" => 1,
    "2013-W5 -> 2013-W8" => 1,
    "2013-W13 -> 2013-W15" => 1
)

I'm trying to sort it like this (so I can use it in a foreach loop):

%errors = (
    "2013-W5 -> 2013-W8" => 1,
    "2013-W9 -> 2013-W12" => 1,
    "2013-W13 -> 2013-W15" => 1
)

I've tried sort keys %errors and sort{$a <=> $b) keys %errors without success.

How can I fix this problem?

Upvotes: 2

Views: 1485

Answers (5)

Arijit Panda
Arijit Panda

Reputation: 1665

I had a similar kind of situation. I solved my problem in the below way:

You tried with

sort keys %errors

and

sort{$a <=> $b) keys %errors

Just try almost a similar thing with a little difference:

Code:

my %errors = (
    "2013-W9 -> 2013-W12" => 1,
    "2013-W5 -> 2013-W8" => 1,
    "2013-W13 -> 2013-W15" => 1);

foreach my $val(sort {my ($anum) = ($a =~ /\d+-\w(\d+)$/);  my ($bnum) = ($b =~ /\d+-\w(\d+)$/);  $anum <=> $bnum} keys %error
{
    print "$val\n";
}

In the above example I have printed the keys only.

Output:

2013-W5 -> 2013-W8
2013-W9 -> 2013-W12
2013-W13 -> 2013-W15

Upvotes: 0

user2404501
user2404501

Reputation:

At The Alphanum Algorithm there's a general string sort routine that compares numeric substrings as numbers, implemented in many languages including Perl.

Upvotes: 2

Slaven Rezic
Slaven Rezic

Reputation: 4581

It seems that in this case the CPAN module Sort::Naturally works fine:

use Sort::Naturally qw(nsort);
say $_ for nsort keys %errors;

Upvotes: 4

Dave Cross
Dave Cross

Reputation: 69284

It's not entirely clear what sort order you want, but this approach can easily be extended:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

my %errors = (
    "2013-W9 -> 2013-W12" => 1,
    "2013-W5 -> 2013-W8" => 1,
    "2013-W13 -> 2013-W15" => 1
);

my @sorted_keys = map { $_->[0] }
  sort { $a->[1] <=> $b->[1] }
  map  { [ $_, /W(\d+)/ ] } keys %errors;

say $_ for @sorted_keys;

Upvotes: 2

mpapec
mpapec

Reputation: 50647

Keys will be sorted for yyyy-Wx in ascending order; first by comparing yyyy and then x numbers,

my @sorted_keys = map $_->[0],
  sort {
    $a->[1] <=> $b->[1]
    ||
    $a->[2] <=> $b->[2]
  }
  map [ $_, /(\d+)/g ],
  keys %errors;

Upvotes: 1

Related Questions