循环遍历包含非引用元素的数组

时间:2014-05-21 20:55:53

标签: arrays perl

如何循环遍历数组数组,如下所示,其中的元素不是引用?我收到错误:"不能使用字符串(" 10")作为ARRAY参考,而#34;严格参考"在使用"但是,如果我拿出元素' 10'和' 11'它打印得很好。

my @array = (
    [1, 2, 3, 4, 5],
    ['x', 'y', 'z'],
    10,
    11
);

foreach my $x (@array) {
   for my $i (0..@$x) {
      if (! @$x[$i] eq '') {
          print "@$x[$i]\n";
      }
   }
}

4 个答案:

答案 0 :(得分:4)

for my $x (@array) {
   # plain scalar, print it and skip to next element
   if (!ref($x)) { print "$x\n"; next; }

   for my $i (@$x) {
      print "$i\n";
   }
}

答案 1 :(得分:2)

这一行:

for my $i (0..@$x) {

是您目前的问题所在。对于@array中的每个值,它会尝试通过@ sigil将其放在Array上下文中。如果您的元素不是对数组的引用,则会抛出您看到的错误。

可以做的是检查你的内循环开始之前是否正在查看arrayref或标量:

ITER:
foreach my $x (@array) {
   if (not ref($x)) {
      print "$x\n";
      next ITER;
   }

   for my $i (0..@$x) {
      if (! @$x[$i] eq '') {
         print "@$x[$i]\n";
      }
   }
}

答案 2 :(得分:1)

您可以使用他ref函数来决定如何打印数组元素。如果参数是数组引用,则返回ARRAY;如果是简单字符串或数值,则返回空字符串。

该程序演示

my @array = (
    [1, 2, 3, 4, 5],
    ['x', 'y', 'z'],
    10,
    11
);

for my $item (@array) {
  if (ref $item) {
    print "@$item\n";
  }
  else {
    print "$item\n";
  }
}

<强>输出

1 2 3 4 5
x y z
10
11

使用条件运算符可以使循环体更简洁。此代码等效

print ref($_) ? "@$_\n" : "$_\n" for @array;

答案 3 :(得分:0)

另一种方法是将任何标量转换为数组引用。这避免了代码重复(以及由此带来的错误风险)。

以你的数组为例:

my @array = (
    [1, 2, 3, 4, 5],
    ['x', 'y', 'z'],
    10,
    11
);

可以使用临时变量来保存原始值 ($row),如果它已经是一个数组引用,或者创建一个数组引用来保存原始值(如果它是一个标量)。从那时起,您可以使用熟值代替原始值。例如:

foreach my $row (@array) {
    my $cooked = ref $row eq 'ARRAY' ? $row : [ $row ];
    print "@$cooked\n";
}

输出:

1 2 3 4 5
x y z
10
11

还可以消除临时变量:

foreach my $row (@array) {
    foreach my $item ( @{ ref $row eq 'ARRAY' ? $row : [ $row ] } ) {
        print "$item\n"
    }
    print "\n";
}

这直接将强制代码作为数组(带有 @{ ... })进行评估并对​​其进行迭代。输出为:

1
2
3
4
5

x
y
z

10

11

可以使用类似的代码,例如,用于哈希引用 (ref $variable eq 'HASH')