-3

I have a sorted hash that I'm converting to two separate arrays, one with keys, one values, how do i keep the arrays sorted like the hash through the process of being converted? I want to be able to use for example array1[0] and array2[0] knowing that they are a key/value pair in the hash. This is how im converting my hash:

my @array1 = keys %hash;
my @array2 = values %hash;

And now the elements of array1 & array2 doesn't display the information in the same order that printing out the sorted key/values would. Is there a way to keep the arrays sorted in the same way as the hash, by value?

NinjaAnte
  • 23
  • 1
  • 5
  • 4
    *“I have a sorted hash”*. No, you don't. Perl hashes are inherently unsorted, and deliberately so. – Borodin Feb 09 '16 at 14:59
  • What i mean by that is that I sorted my hash with a foreach loop by value, are the hashes only sorted within that foreach loop then? Sorry if I misunderstood something. – NinjaAnte Feb 09 '16 at 15:02
  • 1
    I don't see how you can possibly sort anything with a `for` loop. As I have said, if you show the code that you think "sorts" the hash then we will have a better idea of what you are doing – Borodin Feb 09 '16 at 15:07

2 Answers2

1

If I understand correctly, you want both arrays to be sorted by the hash values.

Sort the indices of the second array by the values, then use the resulting list of indices to slice the first array:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my %hash = ( eight => 8,
             five  => 5,
             four  => 4,
             nine  => 9,
             one   => 1,
             seven => 7,
             six   => 6,
             ten   => 10,
             three => 3,
             two   => 2,
           );

my @array1 = keys %hash;
my @array2 = values %hash;

my @indices = sort { $array2[$a] <=> $array2[$b] } 0 .. $#array2;
@array1 = @array1[@indices];
@array2 = @array2[@indices];

say "@array1\n@array2";

Or, sort the keys by value, then map the hash to the keys to get the values:

my @array1 = sort { $hash{$a} <=> $hash{$b} } keys %hash;
my @array2 = map $hash{$_}, @array1;

Use cmp instead of <=> if you want to sort the values alphabetically rather than numerically.

choroba
  • 231,213
  • 25
  • 204
  • 289
  • This assumes that the OP wants the hash elements sorted in alphabetical order of their value, even though you have supposed them to be numeric. That is a very long shot indeed – Borodin Feb 09 '16 at 15:10
  • 1
    Yes, you are sorting the elements alphabetically by value. That is what I wrote. If your example had `ten => 10` then it would be sorted before `two => 2`. And you really have no idea what the OP wants, as all they have said is that they have a sorted hash, which they clearly do not – Borodin Feb 09 '16 at 15:15
  • @Borodin: That wasn't "all they have said". There was also "Is there a way to keep the arrays sorted in the same way as the hash, by value?" – choroba Feb 09 '16 at 15:27
  • @Borodin: Incorrect? – choroba Feb 09 '16 at 15:27
  • @Borodin: Because after your comment I realized it's easier to use `<=>` and add an explanation rather than explain what I had originally in mind. – choroba Feb 09 '16 at 15:29
  • I'd delete the answer, but it's not possible to delete accepted answers. – choroba Feb 09 '16 at 15:30
1

I have a sorted hash

No, you don't. Hashes are inherently unsorted, and deliberately so. You don't show what you have done that makes you think you have "sorted" your hash, but I promise that it is impossible. You could have written

sort %hash

but that will do nothing useful at all, and certainly won't change the hash's contents

All that is guaranteed is that keys and values will return those parts of each element in the same order

If you explain your goal then we will be able to help better

I want to be able to use for example array1[0] and array2[0] knowing that they are a key/value pair in the hash

You can do that anyway. As long as you use keys and values at the same point in your program, and the hash isn't modified in-between, then $hash{$keys[0]} is guaranteed to be $values[0]

If you need to retrieve the contents of your hash in a specific order then you must describe your purpose and say better what you need

Borodin
  • 126,100
  • 9
  • 70
  • 144