user3199303
user3199303

Reputation: 43

How to build a Perl multidimensional array or hash?

I have a set of CSV values like this:

device name, CPU value, frequency of CPU value, CPU in percentage

For example

router1,5,10,4
router1,5,1,5
router2,5,10,4
router2,5,2,5
router3,4,5,6
router3,7,6,5

I need to form a data structure like this:

array = {
    router1 => [5,10,4],[5,1,5],
    router2 => [5,10,4],[5,2,5],
    router3 => [4,5,6],[7,6,5]
}

I need help in forming this data structure in Perl.

I have tried visualizing how to do this but am unable to do so. I would appreciate any help on this.

The end goal for me is to convert this into a JSON object.

Upvotes: 1

Views: 918

Answers (3)

bentastic27
bentastic27

Reputation: 1

In Perl you need to use references in the way of anonymous arrays and hashes to make multidimensional arrays, arrays of arrays, hashes containing hashes and anywhere in between. perlreftut should cover how to accomplish what you are trying to do. Here is an example I wrote the other day that could help explain as well:

print "\nFun with multidimensional arrays\n";
my @myMultiArray = ([1,2,3],[1,2,3],[1,2,3]);

for my $a (@myMultiArray){
    for my $b (@{$a}){
        print "$b\n";
    }
}

print "\nFun with multidimensional arrays containing hashes\nwhich contains an anonymous array\n";
my @myArrayFullOfHashes = (
    {'this-key'=>'this-value','that-key'=>'that-value'},
    {'this-array'=>[1,2,3], 'this-sub' => sub {return 'hi'}},
);

for my $a (@myArrayFullOfHashes){
    for my $b (keys %{$a}){
        if (ref $a->{$b} eq 'ARRAY'){
            for my $c (@{$a->{$b}}){
                print "$b.$c => $c\n";
            }
        } elsif ($a->{$b} =~ /^CODE/){
            print "$b => ". $a->{$b}() . "\n";
        } else {
            print "$b => $a->{$b}\n";
        }
    }
}

Upvotes: 0

Borodin
Borodin

Reputation: 126722

This should get you started. It uses the DATA file handle so that I could embed the data in the program itself. I have used to_json from the JSON module to format the hash as JSON data. The statement $_ += 0 for @values converts the contents of @values from string to to numeric, to avoid quotation marks in the resultant JSON data.

use strict;
use warnings;

use JSON;

my %data;

while (<DATA>) {
  chomp;
  my ($device, @values) = split /,/;
  $_ += 0 for @values;
  push @{ $data{$device} }, \@values;
}

print to_json(\%data, { pretty => 1, canonical => 1 });

__DATA__
router1,5,10,4
router1,5,1,5
router2,5,10,4
router2,5,2,5
router3,4,5,6
router3,7,6,5

output

{
   "router1" : [
      [
         5,
         10,
         4
      ],
      [
         5,
         1,
         5
      ]
   ],
   "router2" : [
      [
         5,
         10,
         4
      ],
      [
         5,
         2,
         5
      ]
   ],
   "router3" : [
      [
         4,
         5,
         6
      ],
      [
         7,
         6,
         5
      ]
   ]
}

Upvotes: 2

jjpcondor
jjpcondor

Reputation: 1416

Here is a simple solution which prints desired JSON object.

#!/usr/bin/env perl    

use strict;
use warnings;
use 5.010;

my %hash;

while (my $line = <DATA>) {
  chomp $line;
  my ($device, @cpu_values) = split(/,/, $line);
  my $cpu_token = join(",", @cpu_values);
  $hash{$device} .= '[' . $cpu_token . '], ';
}

my @devices = keys %hash;

print "array = { \n";
foreach  (sort @devices) {

    print "$_ => [$hash{$_}]\n";

} 
print "}\n";

__DATA__
router1,5,10,4
router1,5,1,5
router2,5,10,4
router2,5,2,5
router3,4,5,6
router3,7,6,5

Upvotes: 0

Related Questions