Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Dynamic array names

by CiceroLove (Monk)
on Feb 09, 2001 at 22:48 UTC ( #57439=perlquestion: print w/replies, xml ) Need Help??

CiceroLove has asked for the wisdom of the Perl Monks concerning the following question:

Howdy all. Just trying to figure out how to make array names on the fly and then reference them later. I don't know exactly how many different arrays of data I am going to have so I need some way nto to hardcode the array names. In other words, I want to make @array1, @array2, @array3, etc., until I don't need arrays any more and can start on the data munging. Any direction for me? Thanks for you help. CiceroLove

Replies are listed 'Best First'.
Re: Dynamic array names
by chromatic (Archbishop) on Feb 09, 2001 at 23:16 UTC
    This is one of the Common Beginner Mistakes. (No offense, any experienced programmer who claims not to have asked the same question once is either Donald Knuth or a liar.)

    If you have a list of items to process and you don't know how long the list will be at compile-time, use a stack. In Perl, that's as simple as using push to add another element to an array. That's exactly what arturo suggests.

    Attempting to keep track of a bunch of names generated on the fly can be tricky, and in this case, it's probably completely unnecessary.

Re: Dynamic array names
by arturo (Vicar) on Feb 09, 2001 at 22:53 UTC

    No big shakes in Perl to do this, but you need to read up on references (perldoc perlref and perldoc perlreftut; in hard copy, I recommend Efficient Perl Programming). What you (probably) want is an *array* of references to arrays.

    my @list_of_arrays; foreach (Thing) { # get array from thing push @list_of_arrays, \@array; } # to get at the arrays foreach my $array (@list_of_arrays) { # $array is a reference to an array foreach (@$array) { # etc } }

    Philosophy can be made out of anything. Or less -- Jerry A. Fodor

      Be very, very careful. You are coming close to the following snippet that I use as an interview question. Suppose that CSV is an open filehandle to a file with comma separated values. You want to extract this into an array of arrays. So you write the following snippet:
      while (<CSV>) { chomp($_); @row = split /,/, $_, -1; push @data, \@row; }
      and you get a list of copies of the last row. Why is it going wrong, and how would you fix?

      When I ask this I am willing to answer any and all questions about syntax, what constructs do, etc. I stand willing to say what the output will be as they make various modifications to the code. The point isn't familiarity with Perl, it is whether you understand how references work.

      Perhaps not surprisingly, I find that people coming from a C background (where you use pointers a lot) tend to do better on this than people who started by learning Perl for scripting/CGI/etc.

        You're right. I could have been more explicit in the original code, but I just wanted to give the gist, and so left large (and potentially important) hunks out. Of course I'd use my @array when I got it from "Thing" (which I'll assume is a line from a file which we're splitting to get an array) , à la :

        my @list_of_arrays; while (<FILE>) { my @array = split "\t", $_; push @list_of_arrays, \@array; }

        Because that gives you a (reference to a) fresh @array each time through the loop, instead of adding yet another reference to the same global array.

        As tilly has pointed out, only giving *parts* of the answer may not be helpful ... So, as they said in that long-ago decade, let's be careful out there =)

        Peevish answer to the interview question: "What, don't you people use strict around here? =)"

        Philosophy can be made out of anything. Or less -- Jerry A. Fodor

Re: Dynamic array names
by Masem (Monsignor) on Feb 09, 2001 at 22:53 UTC
    Are the names that important, or do you just need a hashset of arrays?

    @array_names = ( 'joe', 'bob', 'sue' );
    @array_numbers = ( 3.14, 42, 6, 1e100 );
    %array_hash;
    
    $array_hash{"names"} = \@array_names;
    $array_hash{"numbers"} = \@array_numbers;
    
Re: Dynamic array names
by CiceroLove (Monk) on Feb 10, 2001 at 00:02 UTC
    I guess I didn't give enough information (I'm generally as hard to start as a lawnmower in winter). I am actually walking the MIB tree for some MIBs that are defined in our snmpd.conf as processes. As such, the results of the walk give us , for example:
    1.1:1 1.2:2 1.3:3 2.1:httpd 2.2:sendmail 2.3:portmap 3.1:5 3.2:0 3.3:0 4.1:0 4.2:0 4.3:0 5.1:3 5.2:0 5.3:0 101.1:My error message for httpd 101.2:My error message for sendmail 101.3:My error message for portmap
    This is unchangeable in terms of order. The value before the ':' is the trail of the OID and the value after si the actual data I need in my script to use. But my problem is that the number fo services could change on the fly so I won't know how many services are being monitored. As a result, I need ot be able to take every instance of 2.x:$serviceName and create an array of the values. My approach is to find out how many services and then go back through the list leapgfrogging through the list to get the values which match up with the service. Does that make sense? Me, either. Thanks again. CiceroLove
      OOTOMH:
      my %serviceHash;
      while (<INPUT>) {
          /^(\d*)\.(\d*)\:(\S*)$/;
          if ( !defined( $serviceHash{ $1 } ) ) {
              my @array = ();
              $serviceHash{ $1 } = \@array;
          }
          $($serviceHash{ $1 })[ $2 ] = $3;
      }
      
      You can then do a foreach over the keys of the hash, and do the necessary processing from there. (Update: damn those gt and lt's!)
        If you wish to paste in code, please use the <code>...</code></code> tags. That not only gives easy formatting, but it also makes your code available from clicking on "d/l code".

        UPDATE
        Since tye complained, here is an example of what the CODE tag looks like:

        foreach (split //, "Just another Perl hacker,\n") { print; }
Re: Dynamic array names
by CiceroLove (Monk) on Feb 10, 2001 at 03:27 UTC
    Thanks to everyone that helped me get aroudn the pointer to arrays and hashes of array references and all that mutha jazz. I post my result here. Thsi is my first real foray into arrays and as such I hope is received kindly. Thanks to masem for that lovely snippet just above me. I am going to need a glass fo hogfat to wash that down my mental gullet, so to speak.
    #!/usr/bin/perl use SNMP_util; $nameOID = ".1.3.6.1.4.1.2021.2.1.2"; @addOID = qw(.1.3.6.1.4.1.2021.2.1.3 .1.3.6.1.4.1.2021.2.1.4 .1.3.6.1. +4.1.2021.2.1.5 .1.3.6.1.4.1.2021.2.1.101); $IP = "127.0.0.1"; (@tempNameArray) = &snmpwalk($IP,$nameOID); foreach $a (@tempNameArray) { ($throw, $name) = split(/:/,$a,2); push(@arrayNames, $name); } $control = 0; foreach $i (@arrayNames) { foreach $j (@addOID) { (@breakMe) = &snmpwalk($IP,$j); ($throw, $value) = split(/:/,$breakMe[$control +],2); $resultHash{$i} .= $value.","; } $control++; } foreach $key (keys %resultHash) { ($svcMax, $svcMin, $svcActual, $svcErr) = split(/,/,$resultHas +h{$key}); print "-----------------------\n",$key, " values are:\n"; print "Maximum Services: ", $svcMax, "\n"; print "Minimum Services: ", $svcMin, "\n"; print "Actual Services Running: ", $svcActual, "\n"; print "Error Message: ", $svcErr, "\n"; }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://57439]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2021-07-24 02:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?