28

我有一个$results从服务返回的 perl 变量。该值应该是一个数组,并且$results应该是一个数组引用。但是,当数组中只有一项时,$results将设置为该值,而不是包含该一项的引用数组。

我想foreach在预期的数组上做一个循环。如果不检查ref($results) eq 'ARRAY',有没有办法获得与以下内容等效的内容:

foreach my $result (@$results) {
    # Process $result
}

该特定代码示例将用于参考,但会抱怨简单的标量。

编辑:我应该澄清一下,我无法更改从服务返回的内容。问题在于,当只有一个值时,该值将是一个标量,而当有多个值时,它将是一个数组引用。

4

6 回答 6

26

我不确定除了:

$result = [ $result ]   if ref($result) ne 'ARRAY';  
foreach .....
于 2008-08-06T07:13:16.753 回答
12

另一种解决方案是将调用包装到服务器并让它始终返回一个数组以简化您的余生:

sub call_to_service
{
    my $returnValue = service::call();

    if (ref($returnValue) eq "ARRAY")
    {
        return($returnValue);
    }
    else
    {
       return( [$returnValue] );
    }
}

然后你总是可以知道你会得到一个对数组的引用,即使它只是一个项目。

foreach my $item (@{call_to_service()})
{
  ...
}
于 2008-08-19T14:16:57.493 回答
2

好吧,如果你做不到...

for my $result ( ref $results eq 'ARRAY' ? @$results : $results ) {
    # Process result
}

或这个...

for my $result ( ! ref $results ? $results : @$results ) {
    # Process result
}

那么你可能不得不尝试像这样的毛茸茸的可怕的东西!....

for my $result ( eval { @$results }, eval $results ) {
    # Process result
}

并且为了避免那个危险的字符串评估,它变得非常丑陋!......

for my $result ( eval { $results->[0] } || $results, eval { @$results[1 .. $#{ $results }] } ) {
    # Process result
}

PS。我的偏好是在 reatmon 给出的 sub ala call_to_service() 示例中将其抽象出来。

于 2008-10-12T21:14:12.530 回答
0

我会重新分解循环内的代码,然后做

if( ref $results eq 'ARRAY' ){
    my_sub($result) for my $result (@$results);
}else{
    my_sub($results);
}

当然,如果循环中的代码不平凡,我只会这样做。

于 2008-08-14T21:41:18.903 回答
-1

我刚刚对此进行了测试:

#!/usr/bin/perl -w
use strict;

sub testit {

 my @ret = ();
 if (shift){
   push @ret,1;
   push @ret,2;
   push @ret,3;
}else{
  push @ret,"oneonly";
}

return \@ret;
}

foreach my $r (@{testit(1)}){
  print $r." test1\n";
}
foreach my $r (@{testit()}){
   print $r." test2\n";
}

它似乎工作正常,所以我认为这与从服务返回的结果有关?如果您无法控制退货服务,这可能很难破解

于 2008-08-06T06:22:23.080 回答
-1

你可以这样做:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
于 2016-11-23T05:34:34.953 回答