Search code examples
arraysperliteration

How to Iterate through multiple Perl arrays


I am hoping to make a loop that allows me to use less lines of code to make changes to a settings file with Perl. Currently my code reads an XML file and locates a settings ID and replaces the setting value in that ID with a new one. The current request involves a lot of changes to the settings file and the code is very long. I have set my values in an array and my settings ID's in an array. Like this:

@GreetGoalDP1 = (3, 5, 7, 10);
@GreetSIDSunDP1 = ('//xsd:Settings/xsd:Setting[@SID="7012"]/xsd:Value', 
'//xsd:Settings/xsd:Setting[@SID="7013"]/xsd:Value', 
'//xsd:Settings/xsd:Setting[@SID="7014"]/xsd:Value', 
'//xsd:Settings/xsd:Setting[@SID="7015"]/xsd:Value');

and run the following.

my($matchSunDP1G1) = $xpc->findnodes($GreetSIDSunDP1[0]);
$matchSunDP1G1->removeChildNodes();
$matchSunDP1G1->appendText($GreetGoalDP1[0]);
#GreetB
my($matchSunDP1G2) = $xpc->findnodes($GreetSIDSunDP1[1]);
$matchSunDP1G2->removeChildNodes();
$matchSunDP1G2->appendText($GreetGoalDP1[1]);
#GreetC
my($matchSunDP1G3) = $xpc->findnodes($GreetSIDSunDP1[2]);
$matchSunDP1G3->removeChildNodes();
$matchSunDP1G3->appendText($GreetGoalDP1[2]);
#GreetD
my($matchSunDP1G4) = $xpc->findnodes($GreetSIDSunDP1[3]);
$matchSunDP1G4->removeChildNodes();
$matchSunDP1G4->appendText($GreetGoalDP1[3]);

I would like to run these changes through a loop just using the array [0] - [3] until completed as I have to do this same set of 4 multiple times. I am not too familiar with looping arrays. Is this something I can do in Perl? If so, what would be the most efficient way to do so?


Solution

  • A simple take

    use warnings;
    use strict;
    ...
    
    for my $i (0..$#GreetGoalDP1) {
        my ($matchSunDP1G) = $xpc->findnodes( $GreetSIDSunDP1[$i] );
        $matchSunDP1G->removeChildNodes();
        $matchSunDP1G->appendText( $GreetGoalDP1[$i] );
    }
    

    I take it that you don't need all those individual $matchSunDP1G1 etc. It's assumed that the two arays always have the same length, and their elements are needed in pairs at same indices.

    The syntax $#aryname is for the last index in the array @aryname, and .. is the range operator, so 0 .. $#GreetGoalDP1 for your example is the list 0,1,2,3.

    Then there are libraries that help with use of multiple arrays in parallel, that can be particularly useful when things get messier or more complicated. An example of using an iterator

    use List::MoreUtils qw(each_array);
    
    my $it = each_array @GreetSIDSunDP1, @GreetGoalDP1;
    
    while ( my ($sidsun, $goal) = $it->() ) {
        my ($matchSunDP1G) = $xpc->findnodes($sidsun);
        $matchSunDP1G -> removeChildNodes();
        $matchSunDP1G -> appendText( $goal );
    }
    

    If the lists are uneven in size the iterator keeps going through the length of the longer one. After the shorter one gets exhausted its would-be value is undef.