sort hash key in perl with key being tab separated

Viewed 145

I have a hash of arrays (perl) whose key is a string joined by tabs. This is how the key of the hash looks like

chr"\t"fivep"\t"threep"\t"strand  # separated on tab

If the hash is named %output

I want to sort the keys of this hash such that first the sort is done on chr, then on fivep and then on threep.

I tried the below code for sorting:

foreach my $k(sort keys %output){
    print join("\t",$k,@{$output{$k}}),"\n";    
}

This sort only the chr but I want to sort fivep after it and then threep.

How can I perform that?

2 Answers

I'm going to recommend you do a transform on your keys and then do the custom sort.

for my $k (
    map { $_->[0] } # pull out the original key
    sort { $a->[1] cmp $b->[1] || $a->[2] cmp $b->[2] || $a->[3] cmp $b->[3] } # do the actual sort
    map { [ $_, split /\t/, $_, -1 ] } # split the keys and make the transform
    keys %output
) {
     print join "\t", $k, @output{$k};
}

You can factor the sort code block into it's own function if it's overly complex or this process needs to be reused in more places in the code, as well, then just give the function for sort.

I think https://metacpan.org/pod/Sort::Key::Maker does what you want. The following code should work for you.

use Sort::Key::Maker custom_sort => qw(str str str);
my @sorted = custom_sort { (split /\t/, $_, -1)[ 0 .. 2 ] } keys %output;
Related