Search code examples
arraysperlhash

"Not a HASH reference" error in perl while creating a multi-dimensional hash with its key able to store multiple values


I am trying to create a multidimensional hash with its keys as an array so that the same keys can store multiple values, and is not overridden.

Below is the code snippet:

my %hashR;
my @RelDiv = qw(15.4 dev ques 15.4 dev ques2 15.4 dev2 ques1 15.4 dev2 ques2 
                15.2 dev3 ques2); 
while (my $RName = shift @RelDiv) {
    my $ProStr = shift @RelDiv;
    push @{$hashR{$RName}}, $ProStr;
    my $BName = shift @RelDiv ;    ## Working file till here (tried printing the values)
    push @{$hashR{$RName}{$ProStr}}, $BName;   ###### Error on this line
}

The structure I want is as follows:

{
      '15.4' => {
                   
                   'dev' => [
                                'ques',
                                'ques2'
                            ]
      
                  'dev2' => [
                               'ques1',
                               'ques2'
                             ]
                  
                },
       '15.2' => {
                   'dev3' => [
                                'ques2'
                            ]             
                }

};

But, I am getting an error "Not a HASH reference at file1.pl line". Can anyone please help in resolving the error?

Thanks


Solution

  • You create an array reference when you do this:

    push @{$hashR{$RName}}, $ProStr;
    # means: $hashR{$RName} = [ $ProStr ]
    

    Then you try to use it as a hash ref when you do this:

    push @{ $hashR{$RName}{$ProStr} }, $BName;   ###### Error on this line
    #                    ^^^-- here
    

    Its hard to tell what you want the structure to look like, so I can't really help you with recommendations. Perhaps if you explained what you are trying to achieve, I could help.


    With the new structure update, this is a simple way to do it

    use strict;
    use warnings;
    use Data::Dumper;
    
    my %hash;
    my @RelDiv = qw(15.4 dev ques 15.4 dev ques2 15.4 dev2 ques1 15.4 dev2 ques2 15.2 dev3 ques2); 
    
    while (@RelDiv) {
        my ($RName, $ProStr, $BName) = splice @RelDiv, 0, 3;
        push @{ $hash{$RName}{$ProStr} }, $BName;
    }
    print Dumper \%hash;
    

    Output (the data structure):

    $VAR1 = {
              '15.4' => {
                          'dev2' => [
                                      'ques1',
                                      'ques2'
                                    ],
                          'dev' => [
                                     'ques',
                                     'ques2'
                                   ]
                        },
              '15.2' => {
                          'dev3' => [
                                      'ques2'
                                    ]
                        }
            };
    

    The below criticism remains, however. There is something you're not telling about your data collection, and this solution with splice from an array is not very good. You should go back one step and talk about your data collection.

    Its not a very good way to create a hash, though. If you are just going to assign a list of values to an array at the start, instead assign it to the hash right away and don't do this strange conversion into another structure. Or if you are, as I suspect, reading from a file, again, create the hash structure right away. If you give more detail, I can provide better recommendations.