【问题标题】:perl adds dummy elements to array after inquiryperl 在查询后向数组添加虚拟元素
【发布时间】:2013-01-26 01:13:08
【问题描述】:

正如标题所说,perl 在对不存在的元素进行查询后将虚拟元素添加到数组中。查询后数组大小增加。行为说明:

    my $rarr;
    $rarr->[0][0] = 'S';
    $rarr->[0][1] = 'MD';
    $rarr->[1][0] = 'S';
    $rarr->[1][1] = 'PRP';

    my $crulesref;
    $crulesref->[0]  = $rarr;

     check_rule('aa', 0);
     if($rarr->[3][0] == 'M'){  # just check a not existing element
        print "m\n";   
     }

     check_rule('bb', 0);
     if($rarr->[5][0] == 'M'){  # again: just check a not existing element
        print "m\n";
     }
     check_rule('cc', 0);


     sub check_rule($$)
     {
         my ($strg,$ix) = @_;
         my $aref = $crulesref->[$ix];
         my $rule_size = @$aref;
         {print "-----$strg aref:$aref rs:$rule_size aref:'@$aref'\n";
           for(my $t1 = 0; $t1 <$rule_size; $t1++){
             print "t1:$t1 0:$aref->[$t1][0] 1:$aref->[$t1][1]\n";
           }
         }
       }

运行的结果是:

    en@en-desktop ~/dtest/perl/forditas/utf8_v1/forditas/test1 $ perl v15.pl
    -----aa aref:ARRAY(0x90ed8c8) rs:2 aref:'ARRAY(0x9106cac) ARRAY(0x9106d24)'
    t1:0 0:S 1:MD
    t1:1 0:S 1:PRP
    m                     <-------------- finds the non existing
    -----bb aref:ARRAY(0x90ed8c8) rs:4 aref:'ARRAY(0x9106cac) ARRAY(0x9106d24)          ARRAY(0x9107508)'
    t1:0 0:S 1:MD
    t1:1 0:S 1:PRP
    t1:2 0: 1:               <-- undesired dummy due to inquiry
    t1:3 0: 1:               <-- undesired dummy due to inquiry
    m                      <-------------- finds the non existing
    -----cc aref:ARRAY(0x90ed8c8) rs:6 aref:'ARRAY(0x9106cac) ARRAY(0x9106d24) ARRAY(0x9107904) ARRAY(0x9107508)  ARRAY(0x910e860)'
    t1:0 0:S 1:MD
    t1:1 0:S 1:PRP
    t1:2 0: 1:               <-- undesired dummy due to inquiry
    t1:3 0: 1:               <-- undesired dummy due to inquiry
    t1:4 0: 1:               <-- undesired dummy due to inquiry
    t1:5 0: 1:               <-- undesired dummy due to inquiry

除了在每次询问之前询问是否存在被询问的元素之外,没有其他方法可以避免这种情况吗?我尝试提高速度,但这些查询会减慢代码速度,并使其不易阅读。

提前感谢有用的提示。

【问题讨论】:

  • 发现不存在来自错误的查询。而不是 == 必须使用 eq。然而,这不是主要问题。主要问题是添加元素。

标签: perl


【解决方案1】:

这是您看到的autovivification。如果你访问$ref-&gt;[3][0]的内存,即使只是检查一下:

if ($ref->[3][0] eq 'M' )

那么首先$ref-&gt;[3]必须存在才能检查其元素编号为零,因此它是通过自动生存创建的。您需要先检查$ref-&gt;[3] 是否存在或已定义以避免创建它。

if (defined($ref->[3]) && $ref->[3][0] eq 'M')

此外,您应该始终使用:

use strict;
use warnings;

然后你会看到警告

Argument "M" isn't numeric in numeric eq (==) at ...
Use of uninitialized value in numeric eq (==) at ...

if 子句在这里给出了误报,因为字符串 'M' 被转换为数字 (0),因为数字相等运算符 == 施加的上下文。 LHS 值为undef,它也被转换为一个数字(0),这就是表达式计算结果为真的原因。

【讨论】:

  • if ($ref-&gt;[3] &amp;&amp; $ref-&gt;[3][0] eq 'M') 就足够了
  • @ikegami 是的,但为了演示,具体点也许是个好主意。
  • 如果你真的想要具体一点,那当然应该是if (ref($ref-&gt;[3]) eq 'ARRAY' &amp;&amp; $ref-&gt;[3][0] eq 'M')
  • @IlmariKaronen bless {}, 'ARRAY'
  • @ysth: ... 为什么 你甚至会...? o_O *头疼* 但是好吧,fine,那就让use Scalar::Util qw(reftype); if (reftype($ref-&gt;[3]) eq 'ARRAY' &amp;&amp; $ref-&gt;[3][0] eq 'M')吧。
猜你喜欢
  • 2011-01-24
  • 2012-10-25
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 2012-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多