perl - Perl 哈希数组正在添加来自其他数组的元素
问题描述
我在 perl 5.34.0 中创建了一个哈希数组:
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use autodie ':default';
use DDP;
my (@a1, @a2);
my %h = ('a' => 1);
push @a1, \%h; # make @a1 a hash of array with 'a' defined
$h{b} = 2; # define b within the hash, but don't write to @a1
push @a2, \%h; # push `a` and `b` onto @a2, but *not* @a1
p @a1; # DDP gives "p" which pretty-prints
p @a2;
这输出:
[
[0] {
a 1,
b 2
}
]
[
[0] {
a 1,
b 2
}
]
问题是b
密钥显示在 中@a1
,但$h{b}
在写入数据时不存在@a1
。
我不想b
出现@a1
,也不应该出现。
如何修改%h
,使其不会神奇地出现在不同的数组中?
解决方案
该代码添加了对现有(命名)哈希的引用,
push @a1, \%h;
因此,当稍后查询时,您会看到当时在哈希中看到的任何内容。该数组仅携带一个带有数据地址的指针,也称为哈希;它是某种别名。因此,如果哈希同时被写入,那么这就是您将通过@a1
. †</sup>
再次添加它,即使哈希改变了,您也只需添加相同的旧引用。
您想要的是制作数据副本并添加对其的引用——匿名哈希
push @a1, { %h }; # but may need deep copy instead
现在,哈希数据被复制以填充由构造的匿名哈希,{}
并且我们拥有独立的数据,只能通过其在中的引用写入来更改这些数据@a1
。
但请注意,如果该散列中的值本身是引用,那么这些引用会被复制,我们也会遇到同样的问题!在这种情况下,您需要一个深拷贝,最好使用库来完成;Storable::dclone
是个好人
use Storable qw(dclone);
push @a1, dclone \%h;
现在所有的实际数据都被复制了,用于(参考)一个独立的数据副本@a1
一个重要的例外,经常使用
foreach my $elem (@ary) {
my %h;
# ... code that does its work and populates the hash ...
push @res, \%h;
}
现在这没关系,因为哈希%h
在每次迭代时都会重新创建,并在循环内声明。那么在上一次迭代中创建的数据会发生什么?
由于它的引用被添加到数组中,因此数据本身被保留,由数组中的该引用引用,并且仅由该引用引用。正是您想要的,只能通过数组访问的单独数据。
在这种情况下,这优于push @res, { %h }
,这也有效,因为在保存数据的同时避免了数据复制,也就是说,仅更改其所有权。
†</sup> 并且 ff 数据通过@a1
, like更改$a1[0]->{key} = 'val';
,然后也可以看到新值$h{key}
。
推荐阅读
- reactjs - 当我在反应中按下获取按钮时,对象数组没有被获取
- php - 使用 ajax、jquery 更新多个 HTML 标签
- angular - 来自用户输入的角度获取请求
- javascript - 如果我想导入超过 1 个 CSS 文件,为什么多个 @import 在 Vue.js 项目中不起作用?
- revit - 长度和带值有什么区别
- c# - C# ASP.NET MVC 计算销售税
- python - 扫雷代码在没有最大递归深度的情况下打开零框
- java - 是什么导致我的 Jackson ObjectMapper 序列化输出无效 JSON(键周围没有引号)?
- c++ - GMock:错误:无法将 'cv::MatExpr' 转换为 'bool' 作为回报
- ios - iPhone X 调用伪造的 applicationWillResignActive ,然后调用 applicationDidBecomeActive 不久