Search code examples
arraysperlhashperl-data-structures

More elegant way of accessing hashed arrays


Firstly, appologies if i get any terminology wrong on the upcoming post, this is all still very new to me.

Some background, I have a script that checks our archived network configs for a specific set of settings. As such, the script runs a number of checks, and adds the results to an array for that check.

e.g a check to make sure syslog is configured is added to an array called @internalsyslogerror

after all the checks have run, the arrays for all the checks are added to a hash, with the key being the device name.

note all code has use strict, use warnings

with the following command;

$results{$configs} = [@internalsyslogerror, @bordersyslogerror, 
@borderntperror, @borderntperror, @internalntperror, 
@bordertacacserror, @internaltacacserror, @enablepasswordchecks,
@internalsnmpkeyserror, @timezoneerror, @configregistererror, 
@bannererror, @bootregistererror, @domainnameerror];

The issue im having is what is the most elegant way of extracting this information, i would like to reduce the amount of changes I have to make in order add a new check to the script. Currently i would have to add the additional array to the above code and then add the dereferencing part to the sub that handles that.

Here is currently what i do to de-reference and out put to an array which i then send via an email.

foreach my $k (keys %results) {
    push @results, "<b>$k</b><br>";
    if (defined $results{$k}[0] ){
    push @results, "$results{$k}[0]";
    }
    if (defined $results{$k}[1] ){
    push @results, "$results{$k}[1]";
    }
    if (defined $results{$k}[2] ){
    push @results, "$results{$k}[2]";
    }
    if (defined $results{$k}[3] ){  
    push @results, "$results{$k}[3]";
    }
    if (defined $results{$k}[4] ){
    push @results, "$results{$k}[4]";
    }
    if (defined $results{$k}[5] ){
    push @results, "$results{$k}[5]";
    }
    if (defined $results{$k}[6] ){
    push @results, "$results{$k}[6]";
    }
    if (defined $results{$k}[7] ){
    push @results, "$results{$k}[7]";
    }
    if (defined $results{$k}[8] ){
    push @results, "$results{$k}[8]";
    }
    if (defined $results{$k}[9] ){
    push @results, "$results{$k}[9]";
    }
    if (defined $results{$k}[10] ){
    push @results, "$results{$k}[10]";
    }
    if (defined $results{$k}[11] ){
    push @results, "$results{$k}[11]";
    }
    if (defined $results{$k}[12] ){
    push @results, "$results{$k}[12]";
    }
    if (defined $results{$k}[13] ){
    push @results, "$results{$k}[13]";
    }
}

The question is, can i do what im doing above, but somehow generate the code "on the fly"

Thanks


Solution

  • I haven't seen enough of your code to be certain that this snippet doesn't alter existing behavior. But it should be ok. And it definitely improves maintainability:

    foreach my $k (keys %results) {
        push @results, "<b>$k</b><br>";
        foreach my $index ( 0..$#{$results{$k}} ) {
            if (defined $results{$k}[$index] ){
                push @results, "$results{$k}[$index]";
            }
        }
    }
    

    The above replaces your entire foreach / if construct.