【问题标题】:How to Iterate through multiple Perl arrays如何遍历多个 Perl 数组
【发布时间】:2021-11-26 02:24:10
【问题描述】:

我希望创建一个循环,允许我使用更少的代码行来使用 Perl 更改设置文件。目前,我的代码读取一个 XML 文件并找到一个设置 ID,并将该 ID 中的设置值替换为一个新值。当前请求涉及对设置文件的大量更改,代码很长。我已将我的值设置在一个数组中,并将我的设置 ID 设置在一个数组中。像这样:

@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');

并运行以下命令。

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]);

我想通过循环运行这些更改,只使用数组 [0] - [3] 直到完成,因为我必须多次执行同一组 4 次。我对循环数组不太熟悉。这是我可以在 Perl 中做的事情吗?如果是这样,最有效的方法是什么?

【问题讨论】:

    标签: arrays perl iteration


    【解决方案1】:

    简单介绍

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

    我认为您不需要所有这些单独的 $matchSunDP1G1 等。假设两个数组始终具有相同的长度,并且它们的元素在相同的索引处成对需要。

    语法$#aryname 用于数组@aryname 中的最后一个索引,而..range operator,因此您的示例中的0 .. $#GreetGoalDP1 是列表0,1,2,3

    还有一些库可以帮助并行使用多个数组,当事情变得更混乱或更复杂时,它们会特别有用。使用迭代器的示例

    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 );
    }
    

    如果列表大小不均匀,则迭代器会继续遍历较长列表的长度。在较短的一个用完后,它的可能值为undef

    【讨论】:

    • 感谢您的反馈。我尝试了简单的尝试,并且能够获得要更新的第一个值,但数组中的剩余值没有改变。我相信这可能是因为 $matchSunDP1 也需要随着每个循环而改变。这听起来正确吗?有没有办法将每个循环的数字增加 1,直到 $matchSunDP1 结束?
    • @TaylorStevens 这很奇怪——$GreetSIDSunDP1[$i]$GreetGoalDP1[$i] 元素与在问题中手动输入的元素完全相同。答案中的第一个 sn-p 所做的就是将这些索引放入循环中,而不是手动输入它们。并且$matchSunDP1G 每次都重新创建,甚至重新声明(即前面的my)。我看不出循环有什么不同(错误)?
    • @TaylorStevens 修正了拼写错误 -- 缺少关闭 ),我在名称中添加了 G(这无关紧要)
    • @TaylorStevens 啊,这就解释了。语法$#aryname 用于数组@aryname 中最后一个元素的索引。 (这段代码总是有$#GreetGoalDP1,当你复制它时肯定丢失了。)所以对于@ary = (5,6,7);$#ary2(其中最后一个值的索引,7)。 .. 是“range operator”,当我们说 0 .. 3 时,它会扩展为 (0, 1, 2, 3)。所以0 .. $#ary(在这个例子中是数组)是0..2,所以列表0, 1, 2。在您的问题中有四个元素,因此循环遍历0,1,2,3
    • @TaylorStevens 让我这样说以防万一:确保始终在程序开头使用use warnings;。它可以捕捉各种不好的东西,它真的很有帮助。 (我怀疑这里它会告诉你一些错误,由于复制粘贴错误。)然后另一个好的是use strict;,它迫使你用my声明事情。
    【解决方案2】:

    以下代码示例演示了如何使用%hash 来实现您尝试实现的替代。

    my %hash = (
            3   => '//xsd:Settings/xsd:Setting[@SID="7012"]/xsd:Value',
            5   => '//xsd:Settings/xsd:Setting[@SID="7013"]/xsd:Value',
            7   => '//xsd:Settings/xsd:Setting[@SID="7014"]/xsd:Value',
            10  => '//xsd:Settings/xsd:Setting[@SID="7015"]/xsd:Value')
    );
    
    while( my($k,$v) = each %hash ) {
        my $match = $xpc->findnodes($v);
        $match->removeChildNodes();
        $match->appendText($k);
    }
    

    参考:hashhash operations

    【讨论】:

      【解决方案3】:

      另一种方式,使用来自核心List::Util 模块的zip

      #!/usr/bin/env perl
      use warnings;
      use strict;
      use List::Util qw/zip/;
      
      ...;
      
      my @GreetGoalDP1 = (3, 5, 7, 10);
      my @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');
      
      foreach my $pair (zip \@GreetSIDSunDP1, \@GreetGoalDP1) {
          my ($matchSunDP1G1) = $xpc->findnodes($pair->[0]);
          $matchSunDP1G1->removeChildNodes();
          $matchSunDP1G1->appendText($pair->[1]);
      
      }
      

      【讨论】:

      • 应该版权YAW(另一种方式),好吧,至少广泛传播:)
      • @zdim "TMTOWTDI© 的表达方式不止一种"?
      猜你喜欢
      • 1970-01-01
      • 2010-10-24
      • 2021-12-06
      • 2013-12-11
      • 1970-01-01
      • 1970-01-01
      • 2011-04-11
      • 1970-01-01
      • 2013-03-25
      相关资源
      最近更新 更多