您可以强制标量或数组 ref 成为 Perl 中的数组吗?

Posted

技术标签:

【中文标题】您可以强制标量或数组 ref 成为 Perl 中的数组吗?【英文标题】:Can you force either a scalar or array ref to be an array in Perl? 【发布时间】:2010-09-05 09:51:19 【问题描述】:

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

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

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

那个特定的代码示例可以作为参考,但会抱怨简单的标量。

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

【问题讨论】:

这种行为让我想大喊大叫,“愚蠢的 PERL!”但后来我意识到不需要这种废话的语言仍然在幕后做这件事,这让我的烦恼少了一点...... 【参考方案1】:

我不确定是否有其他方法:

$result = [ $result ]   if ref($result) ne 'ARRAY';  
foreach .....

【讨论】:

【参考方案2】:

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

sub call_to_service

    my $returnValue = service::call();

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

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

foreach my $item (@call_to_service())

  ...

【讨论】:

【参考方案3】:

如果你做不到...

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

为了避免那个危险的字符串 eval 它变得非常丑陋!......

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

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

【讨论】:

这不是字符串评估。循环(一些涉及@$results 的表达式)与循环(@$results)非常不同。前者会复制数组(消耗内存);后者将为其别名(并允许通过循环变量修改元素)。 @ysth - 有...见“eval $results”。我的建议是使用前面给出的 call_to_service() 示例。对于海报施加的限制,我的回答是有点“口中的解决方案”,所以是的,指出它的缺陷是件好事。【参考方案4】:

我会重构循环内的代码,然后再做

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

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

【讨论】:

【参考方案5】:

我刚刚对此进行了测试:

#!/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";

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

【讨论】:

【参考方案6】:

你可以这样做:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array)
  #do something

【讨论】:

虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!

以上是关于您可以强制标量或数组 ref 成为 Perl 中的数组吗?的主要内容,如果未能解决你的问题,请参考以下文章

perl 第五弹 变量 I

Perl:标量,数组,哈希

perl 第六弹 变量 II

Perl:如何解释数组和标量的否定?

5-Perl 变量

在标量上下文中展平 Perl 数组的方法