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. | [reply] |
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 | [reply] [d/l] [select] |
|
|
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. | [reply] [d/l] |
|
|
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 | [reply] [d/l] [select] |
|
|
|
|
|
|
|
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;
| [reply] |
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 | [reply] [d/l] |
|
|
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!)
| [reply] |
|
|
foreach (split //, "Just another Perl hacker,\n") {
print;
}
| [reply] [d/l] |
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";
}
| [reply] [d/l] |