Perl中哈希结构的深度拷贝
来源:互联网 发布:新东方烹饪学校 知乎 编辑:程序博客网 时间:2024/05/11 21:42
下午修改一段Perl代码的时候,遇到了一个深度拷贝的问题。废话少说,上代码:
my ($rc, $refdata) = db_query($sql_text, "hashref"); unless ($rc) { return ($rc, $refdata); } my @arrayhash = (); foreach my $ref (@$refdata) { # 这里$ref->{host_ip}的值为"10.136.142.205,127.0.0.1" if (defined($ref->{"is_logserver_log"}) && $ref->{"is_logserver_log"} eq "y" && defined($ref->{"host_ip"})) { foreach my $host (split(/,/, $ref->{"host_ip"})) { $ref->{"host_ip"} = $host; if ($ref->{"host_ip"} eq "127.0.0.1") { write_log("1 " . Dumper($ref) . "\n") } push @arrayhash, $ref; } } else { push @arrayhash, $ref; } } foreach my $tmp (@arrayhash) { if ($tmp->{"host_ip"} eq "127.0.0.1") { write_log("3 " . Dumper($tmp) . "\n") } }
上面这段代码用于将数据库中的记录集存入一个Hash数组,这段代码的执行结果在1处打印两次,但在3处却打印4次。显然不符合预期。
多出来的两条记录哪儿来的呢,唯一可能的就是内层的foreach以及push过程:
于是修改内层foreach代码为深度拷贝如下,测试OK:
foreach my $host (split(/,/, $ref->{"host_ip"})) { my $elem; $elem->{$_} = $ref->{$_} foreach keys %$ref; $elem->{"host_ip"} = $host; push @arrayhash, $elem; }
原来在内层foreach中$ref被修改时,并没有执行CopyOnWrite(写时复制)的过程,而是直接修改了$ref指向内容的值,即这里一直是浅拷贝。从而导致$ref指向的变量被修改,然后又被覆盖,改为深度拷贝后问题解决。
上面的深度拷贝只能拷贝一层Hash结构,如果数据结构更复杂一点便无法支持,这里提供一个支持任意复杂程序基于递归的深度拷贝函数:
use Scalar::Util qw(reftype refaddr);sub real_copy{ my ($value, $cloned) = @_; return $value unless (ref($value)); my $addr = refaddr($value); return $cloned->{$addr} if (exists($cloned->{$addr})); my ($ref_type, $copy) = reftype($value); if ($ref_type eq 'ARRAY') { $copy = []; $cloned->{$addr} = $copy; push(@$copy, map { real_copy($_, $cloned) } @$value); } elsif ($ref_type eq 'HASH') { $copy = {}; $cloned->{$addr} = $copy; foreach my $key (keys(%{$value})) { $copy->{$key} = real_copy($value->{$key}, $cloned); } } elsif ($ref_type eq 'SCALAR') { $copy = \do{ my $scalar = $$value; }; $cloned->{$addr} = $copy; } elsif ($ref_type eq 'REF') { if ($addr == refaddr($$value)) { $copy = \$copy; $cloned->{$addr} = $copy; } else { my $tmp; $copy = \$tmp; $cloned->{$addr} = $copy; $tmp = real_copy($$value, $cloned); } } return $copy;}
- Perl中哈希结构的深度拷贝
- 结构体及其应用:结构体的深度拷贝,结构体内含指针
- 深度拷贝的重要性
- C++的深度拷贝
- 对象的深度拷贝
- Flex:对象的深度拷贝
- 深度拷贝、浅度拷贝、数组的拷贝
- perl 文件目录的创建删除拷贝
- 深度拷贝
- 结构的浅拷贝验证
- python 的拷贝、深度拷贝及内存管理
- [NET]深度拷贝的实现(DeepCopy)
- as3.0深度拷贝--新的内存空间
- 深度拷贝的语法和实现
- List.toArray()采用的是深度拷贝
- Lua Table表的深度拷贝
- Java编程基础-----对象的深度拷贝
- 三种深度拷贝方式的比较
- ibatis源码浅析- 初始化
- Perl函数的声明与调用
- Perl中foreach循环变量
- Perl中的each方法
- Android Activity生命周期 .
- Perl中哈希结构的深度拷贝
- Perl获取指定进程的子进程
- lsof命令导致CPU负载异常的问题总结
- SVN服务器IP被修改的客户端连接解决方案
- Xtrabackup 热备份与还原
- 单链表操作_头结点方式
- C#99乘法表
- C#打印等腰三角形
- C# 打印菱形