检测混合数组中的元素类型

时间:2016-09-12 03:45:10

标签: arrays perl ref scalar

我正在使用一些具有子程序的代码,该子程序包含一个数组引用作为参数之一。此传入数组中的元素可以是小数组或字符串。

我想确定每个元素的类型以便执行特定的操作(即,如果元素是数组,通过索引进一步深入,如果元素是字符串,则使用字符串)

我尝试使用ref函数来查询每个数组元素。它似乎适用于ARRAYs的元素,但如果元素是一个字符串,我希望ref返回SCALAR。但是ref()似乎什么也没有回复。我究竟做错了什么?我认为ref()会返回一些东西。

以下是一些示例代码:

my @array = ("string1", 
             ["ele1_arraystr1", "ele1_arraystr2"], 
             "string2", 
             ["ele4_arraystr1", "ele4_arraystr2"], 
             "etc");
my $tmp;
&foobar( 30, 20, \@array);

sub foobar {
    my($var1, $var2, $array_ref) = @_;
    foreach $element (@$array_ref) {
        my $tmp = ref($element);
        print "Array element type: $tmp\n";
        if ($tmp eq 'ARRAY') {
            print "  ARRAY: $element->[1]\n";

        } elsif ($tmp eq 'SCALAR') {
            print "  SCALAR: $element\n";
        } else {
            print "  Unexpected type: $tmp\n";
       }
    }
 }

输出看起来像这样:

ARRAY element test:
Array element type: 
  Unexpected type: 
Array element type: ARRAY
  ARRAY: ele1_arraystr2
Array element type: 
  Unexpected type: 
Array element type: ARRAY
  ARRAY: ele4_arraystr2
Array element type: 
  Unexpected type: 

2 个答案:

答案 0 :(得分:5)

ref如果参数不是引用,则返回一个空字符串。文件说

  

如果EXPR是引用,则返回非空字符串,否则返回空字符串。返回的值取决于引用引用的事物的类型。

下面的列表(包括SCALAR)是引用可以使用的类型。

因此,当它有一个字符串时,它返回一个空字符串,其值为false。如果您知道它是ARRAY或字符串,那么您可以

if (ref($element) eq 'ARRAY') {
    # process the arrayref
}
else { 
    # process the string
}

更好地检查字符串(false),就像你一样,以便能够检测任何其他类型

my $ref_type = ref($element);
if ($ref_type eq 'ARRAY') {
    # process arrayref
}
elsif (not $ref_type) {  
    # process string
}
else { print "Got type $ref_type\n" }

答案 1 :(得分:4)

所有这些都记录在perldoc perlfunc under ref

中 如果

ref的参数不是引用,则会返回 false 值。仅当参数是标量的引用

时,它才会返回SCALAR

您可能还需要知道,对于祝福数据的引用 - 一个Perl对象 - ref返回数据已被祝福的 ,而不是基础数据类型。如果你需要区分这两者,那么核心Scalar::Util模块提供blessed,它返回数据已被祝福的类,以及reftype,它返回的类型基础数据与ref

的方式相同

您可以让foobar递归来处理无限期嵌套的数据结构,例如

use strict;
use warnings 'all';
use feature 'say';

my @array = (
    "string1", [ "ele1_arraystr1", "ele1_arraystr2" ],
    "string2", [ "ele4_arraystr1", "ele4_arraystr2" ],
    "etc",     [ "etc1", "etc2" ]
);

foobar(\@array);

sub foobar {
    my ($val, $indent) = (@_);
    $indent //= 0;
    my $ref = ref $val;

    if ( $ref eq 'ARRAY' ) {
        foobar($_, $indent+1) for @$val;
    }
    elsif ( not $ref ) {
        say '  ' x $indent, $val;
    }
}

输出

  string1
    ele1_arraystr1
    ele1_arraystr2
  string2
    ele4_arraystr1
    ele4_arraystr2
  etc
    etc1
    etc2

或者,如果您的数组始终由交替的字符串和数组引用组成,您可能会发现将其分配给哈希更容易。这将使用字符串作为散列键及其对应的数组引用作为散列值

此代码显示了这个想法。我使用Data::Dump来揭示结果数据结构

my %data = @array;

use Data::Dump;
dd \%data;

输出

{
  etc => ["etc1", "etc2"],
  string1 => ["ele1_arraystr1", "ele1_arraystr2"],
  string2 => ["ele4_arraystr1", "ele4_arraystr2"],
}