【问题标题】:What happens if we change/update a hash value inside an each loop?如果我们在每个循环中更改/更新哈希值会发生什么?
【发布时间】:2012-10-13 16:51:45
【问题描述】:

“perldoc -f each”告诉我在迭代时删除或添加值是不安全的,除非该项目是 each() 最近返回的。

当我运行这段代码时:

my ($key,$value);

my %fruits = qw/ banana 1 apple 2 grape 3 /;

while ( $key = each %fruits ) {
    $fruits{$key} *= 7;
    print "$key = $fruits{$key}\n";
}

print "\nRead only\n\n";

while ( ($key,$value) = each %fruits ) {
    print "$key = $value\n";
}

一切正常!

但如果我使用绑定哈希,嗯:

#-------------------------------------------------------------------------------
# select entries on database to print or to update.
sub select_urls {
    my ($dbPath,$match,$newValue) = @_;

    tie(my %tiedHash,'DB_File',$dbPath,O_RDWR|O_EXLOCK,0600,$DB_BTREE) || die("$program_name: $dbPath: $!\n");

    while ( my($key,$value) = each %tiedHash ) {
        if ( $key =~ $match ){
            if ( defined $newValue ) {
                $tiedHash{$key} = $newValue;
                ($key,$value) = each %tiedHash; # because 'each' come back 1 step when we update the entry
                print "Value changed --> $key = $value\n";
            } else {
                print "$key = $value\n";
            }
        }
    }

    untie(%tiedHash) ||  die("$program_name: $dbPath: $!\n");
}

需要第二次调用 each()。

我必须'perl -v':

$ perl -v

这是 perl 5, version 12, subversion 2 (v5.12.2 (*)) 为 amd64-openbsd(有 8 个注册补丁,详情见 perl -V)

版权 1987-2010,拉里·沃尔 ...

我在想这是不是一个错误?!!

也许还有更多的事情在幕后......

我问我的解决方案是否正确???

【问题讨论】:

    标签: perl function hash each tie


    【解决方案1】:

    问题在于元素(键)的添加或删除。更改值应该没有问题。绑定哈希没有本质上的区别。

    my ($key,$value);
    
    use Tie::Hash;
    
    tie my %fruits, 'Tie::StdHash';
    %fruits = qw/ banana 1 apple 2 grape 3 /;
    
    while ( $key = each %fruits ) {
        $fruits{$key} *= 7;
        print "$key = $fruits{$key}\n";
    }
    
    print "\nRead only\n\n";
    
    while ( ($key,$value) = each %fruits ) {
        print "$key = $value\n";
    }
    

    输出:

    banana = 7
    apple = 14
    grape = 21
    
    Read only
    
    banana = 7
    apple = 14
    grape = 21
    

    您的第二个 sn-p 没有显示错误。它并没有表现出太多的东西。它不可运行,你没有指定它输出什么,你也没有指定你期望它输出什么。但是让我们看看DB_File是否有问题。

    use DB_File qw( $DB_BTREE );
    use Fcntl   qw( O_RDWR O_CREAT );  # I don't have O_EXLOCK
    
    my ($key,$value);
    
    tie(my %fruits, 'DB_File', '/tmp/fruits', O_RDWR|O_CREAT, 0600, $DB_BTREE)
       or die $!;
    %fruits = qw/ banana 1 apple 2 grape 3 /;
    
    while ( $key = each %fruits ) {
        $fruits{$key} *= 7;
        print "$key = $fruits{$key}\n";
    }
    
    print "\nRead only\n\n";
    
    while ( ($key,$value) = each %fruits ) {
        print "$key = $value\n";
    }
    

    没有。

    apple = 14
    banana = 7
    grape = 21
    
    Read only
    
    apple = 14
    banana = 7
    grape = 21
    

    【讨论】:

    • 对不起!如果没有第二次调用,代码将无限期地运行。我认为,当它更新值时,每个索引都会后退 1。然后对每个的下一次调用再次获得相同的条目。我看到的是一对重复的键,值与新值一起打印。
    • 预期是与新值匹配的 URL 列表。 (我通过对每个调用的第二次调用实现了这一点)。
    • ikegammi,我运行了你的代码,我得到了:apple = inf apple = inf apple = inf apple = inf apple = inf apple = inf
    • 然后我运行了 'perl each-ikegami.pl |头”得到:苹果 = 14 苹果 = 98 苹果 = 686 苹果 = 4802 苹果 = 33614 苹果 = 235298 苹果 = 1647086 苹果 = 11529602 苹果 = 80707214 苹果 = 564950498
    • Perl 5.16.0(线程)、DB_File 1.826、Berkeley DB 4.8.30(我认为)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-24
    • 2014-10-28
    相关资源
    最近更新 更多