in reply to Re: Array of Arrays on Monday.
in thread Array of Arrays on Monday.

the array should look as follows. For each of 250K lines I should push the application name, and then the IP address to the proper application name. Only keeping the unique changes. One application may end up with thousands of members. and there are over 4000 unique application names. I need to create a CSV file of application names by member and the member column will use the ";" as a separator not to interfere with the comma.

A = ( application1 => [ "10.10.10.1", "10.10.10.2" ], application2 => [ "10.10.10.3", "10.10.10.4", "10.10.10.5" ], application3 => [ "10.10.10.1", "10.10.10.3", "10.10.10.6" ], );

Replies are listed 'Best First'.
Re^3: Array of Arrays on Monday.
by choroba (Cardinal) on Jan 25, 2016 at 15:56 UTC
    So, don't you miss a % before the A, i.e. aren't you trying to create a hash of arrays rather than an array of arrays?
    my %application; # <-- Hash! print "Application = ", $data[$application_pos], "\n"; if ( $data[$application_pos] ne "" && $data[$ip_address_pos] ne "" ) { my $key = $data[$application_pos]; push @{ $application{$key} }, $data[$ip_address_pos]; # Pushing t +o a HoA. print Dumper( \%application ) ; }

    Update: Fixed signature.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      For some reason it is generating the following error.

      Global symbol "@application" requires explicit package name (did you f +orget to declare "my @application"?) at ServiceNowCMDB2ARX.pl line 21 +2. Global symbol "@application" requires explicit package name (did you f +orget to declare "my @application"?) at ServiceNowCMDB2ARX.pl line 21 +4.
        my %application;
        ...
        $application[$key] = $data[$application_pos];

        I think this line from here should be
            $application{$key} = $data[$application_pos];
        (square [] vice {} curlies).

        Update: Line in question was changed to
            my $key = $data[$application_pos];


        Give a man a fish:  <%-{-{-{-<

Re^3: Array of Arrays on Monday.
by poj (Abbot) on Jan 25, 2016 at 17:27 UTC
    Only keeping the unique changes

    If this means ignoring duplicates use a HashOfHashes (HOH)

    #!perl use strict; use Data::Dumper; my %hash=(); while (<DATA>){ chomp; my ($name,$ip) = (split)[0,1]; if ( $name ne "" && $ip ne "" ) { ++$hash{$name}{$ip}; } } my %application=(); for my $name (keys %hash){ $application{$name} = [sort keys %{$hash{$name}}]; } print Dumper( \%application ) ; __DATA__ application1 10.10.1 application1 10.10.2 application3 10.10.1 application3 10.10.3 application2 10.10.3 application2 10.10.4 application2 10.10.5 application3 10.10.6 application1 10.10.1 application1 10.10.1
    poj

      I need Hash of Hashes.... But here,s the rub. All these lines are CI records from a ServiceNow CMDB. So I screwed up thinking the application name was on the same line. The application name is only the CI ( CI10335478 ). Now I need to look up the name of the CI and all applications have a sys_class_name = "cmdb_ci_appl" Its just that I need a placeholder for Application Name because the line containing that may be 10000 lines or more down the data. But I need a place holder for application name until it comes along and we can populate it. This is because the ouput data need to look like this.

      Status,Name,Description,Members,Id,InboundUtilizationBandwidth,Outboun +dUtilizationBandwidth,Appliances,CollectOnDirector ,app_name1,CI10335478,MemberIP1;MemberIP2;MemberIP6,,,,, ,app_name2,CI10334984,MemberIP4;MemberIP2,,,,,

      So what I need is to buld out the following array.

      $VAR1 = { 'CI10335478' => 'app_name1' => MemberIP 1, MemberIP 2, MemberIP 6 ], 'CI10334984' => 'app_name2' => MemberIP 4, MemberIP 2, }; our %application = (); sub add_to_application_members { my ($app_ci, $member_ip, $value) = @_; $application{$app_ci{$member_ip}} = $value; } sub add_to_application_names { my ($member, $value) = @_; $application{$member} = $value; } if ( $data[$class_pos] eq "cmdb_ci_appl" ) { add_to_application_names( $data[$ci_pos] => $data[$name_pos] ); print Dumper( %application ) ; } if ( $data[$application_pos] ne "" && $data[$ip_address_pos] ne "" ) { add_to_application_members( $data[$application_pos] => $data[$ip_add +ress_pos] ); print Dumper( %application ) ; } _DATA_ u_ci_id,sys_class_name,application,ip_address ,name CI12345,cmdb_ci_appl , , ,foobar1 CI56789,cmdb_ci_svr ,CI12345 ,10.10.10.10, hostname1

        Would this work ?. You may find it easier to build.

        my %application = ( 'CI10335478' => { name => 'app_name1', IP => [ 'MemberIP 1', 'MemberIP 2', 'MemberIP 6', ], }, 'CI10334984' => { name => 'app_name2', IP => [ 'MemberIP 4', 'MemberIP 2', ], }, );
        poj

      poj is on the right track, and for some reason, I got myself confused and am stuck now. So he sent this.

      my %application = ( 'CI10335478' => { name => 'app_name1', IP => [ 'MemberIP 1', 'MemberIP 2', 'MemberIP 6', ], }, 'CI10334984' => { name => 'app_name2', IP => [ 'MemberIP 4', 'MemberIP 2', ], }, );

      I have 250K records in XML that are parsing correctly. So now I need to get them into the hash. $data$name_pos contains the application name on application CI's. $data$application_pos contains the CI of the application we need to look up $data$name_pos on device CI's So $application_pos and $data$ci_pos should be equal. I have to process > 5K of records to start getting intersections of the data, and I don't want to put that here, and its all in XML. So my idea was to write my data to the hash or array when I come across them. So I don't have a blob to just push into the structure.

        Use a separate hash for the names and combine them with IPs at the end

        #!perl use strict; use Data::Dump 'pp'; my %tmp =(); my %name=(); my $header = <DATA>; while(<DATA>){ chomp; my ($u_ci,$class,$app,$ip,$name) = split ',',$_; if ($class eq 'cmdb_ci_appl'){ $name{$u_ci} = $name; } elsif ($class eq 'cmdb_ci_svr'){ $tmp{$app}{$ip}=1; } else { print "$class\n"; } } my %application = (); for my $app (keys %tmp){ $application{$app}{'IP'} = [sort keys %{$tmp{$app}}]; $application{$app}{'name'} = $name{$app}; } pp \%application ; __DATA__ u_ci_id,sys_class_name,application,ip_address ,name CI56789,cmdb_ci_svr,CI10335478,MemberIP 1,hostname1 CI56789,cmdb_ci_svr,CI10335478,MemberIP 2,hostname1 CI56789,cmdb_ci_svr,CI10335478,MemberIP 6,hostname1 CI56789,cmdb_ci_svr,CI10334984,MemberIP 4,hostname1 CI56789,cmdb_ci_svr,CI10334984,MemberIP 2,hostname1 CI10334984,cmdb_ci_appl,,,app_name2 CI10335478,cmdb_ci_appl,,,app_name1
        poj