Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I preserve the order of a hash in Perl?

Tags:

hash

perl

I have a .sql file from which I am reading my input. Suppose the file contains the following input....

Message Fruits Fruit="Apple",Color="Red",Taste="Sweet";

Message Flowers Flower="Rose",Color="Red";

Now I have written a perl script to generate hash from this file..

use strict;
use Data::Dumper;

if(open(MYFILE,"file.sql")){
    my @stack;
    my %hash;
    push @stack,\%hash;
    my @file = <MYFILE>;
    foreach my $row(@file){
        if($row =~ /Message /){
            my %my_hash;
            my @words = split(" ",$row);
            my @sep_words = split(",",$words[2]);

            foreach my $x(@sep_words){
                my($key,$value) = split("=",$x);
                $my_hash{$key} = $value;
            }
            push @stack,$stack[$#stack]->{$words[1]} = {%my_hash};
            pop @stack;
        }
    }
    print Dumper(\%hash);
}

I am getting the following output..

$VAR1 = {
          'Flowers' => {
                         'Flower' => '"Rose"',
                         'Color' => '"Red";'
                       },
          'Fruits' => {
                        'Taste' => '"Sweet";',
                        'Fruit' => '"Apple"',
                        'Color' => '"Red"'
                      }
        };

Now here the hash is not preserving the order in which the input is read.I want my hash to be in the same order as in input file. I have found some libraries like Tie::IxHash but I want to avoid the use of any libraries.Can anybody help me out???

like image 561
rai-gaurav Avatar asked Dec 11 '22 18:12

rai-gaurav


2 Answers

For a low key approach, you could always maintain the keys in an array, which does have an order.

foreach my $x(@sep_words){
    my($key,$value) = split("=",$x);
    $my_hash{$key} = $value;
    push(@list_keys,$key);
}

And then to extract, iterate over the keys

foreach my $this_key (@list_keys) {
    # do something with $my_hash{$this_key}
}

But that does have the issue of, you're relying on the array of keys and the hash staying in sync. You could also accidentally add the same key multiple times, if you're not careful.

like image 60
matt freake Avatar answered Jan 01 '23 14:01

matt freake


Joel has it correct - you cannot reliably trust the order of a hash in Perl. If you need a certain order, you'll have to store your information in an array.

like image 27
Mike Avatar answered Jan 01 '23 14:01

Mike