Printing content of hash of arrays of arrays

Viewed 86

I've been trying to read the following structure in Perl:

my %Homes = (
          "Home 1" => [
          'TYPE_OF_HOUSE' => "Villa",
          'FIELD1' => ["1","2","3"],
          'Field2' => ["2","3","4"],
          'Field3' => ["3","4","5"],
      ],
      "Home 2" => [
          'TYPE_OF_HOUSE' => "Duplex",
          'FIELD1' => ["1","2","3"],
          'Field2' => ["2","3","4"],
          'Field3' => ["3","4","5"],
      ],
      "Home 3" => [
          'TYPE_OF_HOUSE' => "Apartment",
          'FIELD1' => ["1","2","3"],
          'Field2' => ["2","3","4"],
          'Field3' => ["3","4","5"],
      ],
  );

By using the following:

my @data_Array;
my ($inner_Key,$key,$names_ref);
foreach $key (keys %Homes)
 {
  print("Inner values of house $key are:");

  foreach $inner_Key ( @{$Homes{$key}})
   {
    if ($inner_Key != "TYPE_OF_HOUSE")
     {
      $names_ref  = \@$inner_Key;
      @data_Array = @{$names_ref};
      print($data_Array[0]);        
      print($data_Array[1]);      
      print($data_Array[2]);      
     }
    else
     {
      print($inner_Key);
     }
  }
}

I successfully printed the: "Home 1", "Home 2", but when trying to read the inner content, even though I used reference to an array, it didn't go well. What did I miss? My goal was to "identify" the type of field, and if it was TYPE_OF_HOUSE, then simply print it because it is not an array. Otherwise, print the inner content of its array.

1 Answers

You must use strict and warnings because they will tell you a lot about what is wrong with your code.

You need to use ne instead of != when comparing strings.

You should use a different data structure to make it simpler to access inner data elements. You have a hash-of-arrays, but it would make more sense as a hash-of-hashes. By using => for 'TYPE_OF_HOUSE' => "Villa", you've tricked yourself into believing that is a hash. However, it is just a flat array. The 1st element of the array is TYPE_OF_HOUSE, the 2nd element is Villa, the 3rd is FIELD1, the 4th is an array ref, etc.

use warnings;
use strict;

my %Homes = (
    "Home 1" => {
        'TYPE_OF_HOUSE' => "Villa",
        'FIELD1'        => [ "1", "2", "3" ],
        'Field2'        => [ "2", "3", "4" ],
        'Field3'        => [ "3", "4", "5" ],
    },
    "Home 2" => {
        'TYPE_OF_HOUSE' => "Duplex",
        'FIELD1'        => [ "1", "2", "3" ],
        'Field2'        => [ "2", "3", "4" ],
        'Field3'        => [ "3", "4", "5" ],
    },
    "Home 3" => {
        'TYPE_OF_HOUSE' => "Apartment",
        'FIELD1'        => [ "1", "2", "3" ],
        'Field2'        => [ "2", "3", "4" ],
        'Field3'        => [ "3", "4", "5" ],
    },
);

my @data_Array;
my ( $inner_Key, $key, $names_ref );
foreach $key ( keys %Homes ) {
    print("Inner values of house $key are:");
    print "\n";

    foreach $inner_Key ( keys %{ $Homes{$key} } ) {
        if ( $inner_Key ne "TYPE_OF_HOUSE" ) {
            @data_Array = @{ $Homes{$key}{$inner_Key} };
            print( $data_Array[0] );
            print "\n";
            print( $data_Array[1] );
            print "\n";
            print( $data_Array[2] );
            print "\n";
        }
        else {
            print($inner_Key);
            print "\n";
        }
    }
}

I used perltidy to improve the indentation. I added newlines to make your print output easier to read.

Related