Perl中的each方法

    each函数用以一次一个键字/数值对的方式遍历一个散列。

    在散列内部,它以一种看上去是随机的顺序维护它自己的记录。each 可以遍历这个序列是因为每个散列都记得上一次返回的是哪条记录。这个序列的实际的顺序可能在将来的 Perl 版本里会改变,但有一点可以保证,就是 keys(或者 values)函数在同一个(未修改)的散列上生成的顺序是一样的。
    每个散列都有一个遍历器,由在该程序里所有的 each,keys,和 values 函数调用共享;该遍历器可以通过从散列里读取所有元素来重置,或者通过计算 keys %hash 或 values %hash 来重置。如果你在遍历散列的过程中删除了元素,那么后果还没有很好的定义:记录可能会被忽略也可能被重复。

    因为each函数每次只返回一对键值而不是返回整个列表,所以必须记录上一次的访问位置。
    关于遍历器对位置的记录,见下面示例:

    #!/usr/bin/perl -w
    ##############################
    use strict;
    my %hash = ( 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6,);
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
        last if($k eq "3");
    }
    print "----------------------\n";
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
    }


    执行代码,输出如下:

    $ ./test.pl 
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    ----------------------
    2  =>  2
    5  =>  5


  显然,each函数的内部遍历器记录了上次遍历的位置,第二次遍历时从前一次的位置开始。

  如果第一次遍历到哈希尾部,则下次开始时会从首部开始遍历:

    #!/usr/bin/perl -w
    ##############################
    use strict;
    my %hash = ( 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6,);
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
    }
    print "----------------------\n";
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
    }


  输出如下:

    $ ./test.pl 
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    2  =>  2
    5  =>  5
    ----------------------
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    2  =>  2
    5  =>  5


如果第一次遍历并没有到达尾部,但使用 keys 重置一次遍历器,下次也会从开头开始遍历,如下:

    #!/usr/bin/perl -w
    ##############################
    use strict;
    my %hash = ( 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6,);
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
        last if($k eq "3");
    }
    print "----------------------\n";
    keys %hash;
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
    }


  输出:

    $ ./test.pl 
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    ----------------------
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    2  =>  2
    5  =>  5


  这里的遍历器记录的是哈希本身的遍历位置,而不是变量或引用名称,如:

    #!/usr/bin/perl -w
    ##############################
    use strict;
    my %hash2 = ( x => { 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, });
    while(my ($K, $V) = each(%hash2)){
        while(my ($k, $v) = each(%$V)){
            print "$k  =>  $v\n";
            last if($k eq "3");
        }
    }    
    print "----------------------\n";
    while(my ($K, $V) = each(%hash2)){
        while(my ($k, $v) = each(%$V)){
            print "$k  =>  $v\n";
        }
    } 


  输出如下:

    $ ./test.pl 
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    ----------------------
    2  =>  2
    5  =>  5


显然,这里的遍历二级子哈希时使用了临时变量,但Perl仍然记录了变量的访问位置。

而且,Perl的内部遍历器是全局生效的,而不是像变量名那样只在块作用域中生效。

    #!/usr/bin/perl -w
    ##############################
    use strict;
    my %hash = ( 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6,);
    if(1){
        while(my ($k, $v) = each(%hash)){
            print "$k  =>  $v\n";
            last if($k eq "3");
        }
    }
    print "----------------------\n";
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
    }


输出:

    $ ./test.pl 
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    ----------------------
    2  =>  2
    5  =>  5


显然,第一次遍历尽管用了块作用域,但仍然影响了第二次遍历的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值