- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如下所示,我有一个 foreach 循环,其中哈希数组中的值将被另一个哈希数组中的值替换。
第二个 foreach 循环只是打印并测试值是否分配正确。
foreach my $row (0 .. $#row_buff) {
$row_buff[$row]{'offset'} = $vars[$row]{'expression'};
print $row_buff[$row]{'offset'},"\n";
}
foreach (0 .. $#row_buff) {
print $row_buff[$_]{'offset'},"\n";
}
这里@row_buff和@vars是两个哈希数组。它们预先填充了所有使用的键的值。
哈希值被插入数组,如下所示:
push @row_buff, \%hash;
问题:假设第一个 foreach 打印中的打印语句如下所示:
string_a
string_b
string_c
string_d
然后第二个 foreach 循环中的打印语句如下所示:
string_d
string_d
string_d
string_d
这就是我困惑的地方。两个打印语句应该以完全相同的方式打印,对吗?但是第二个打印语句打印的值只是重复方式的最后一个值。有人可以指出我这里可能出了什么问题吗?任何提示都将不胜感激。这是我第一次提出问题,如果我遗漏了什么,请原谅我。
更新
我可以添加一些信息,对此大家表示歉意。在 foreach 之前还有一行,就像这样:
@row_buff = (@row_buff) x $itercnt;
foreach my $row (0 .. $#row_buff) {
$row_buff[$row]{'offset'} = $vars[$row]{'expression'};
print $row_buff[$row]{'offset'},"\n";
}
foreach (0 .. $#row_buff) {
print $row_buff[$_]{'offset'},"\n";
}
$itercnt 是一个整数。我用它多次复制 @row_buff。
最佳答案
这显然与在数组上存储引用有关,而不是独立数据。由于没有给出详细信息,因此尚不清楚这是如何发生的,但以下讨论应该会有所帮助。
考虑这两个基本示例。
首先,在数组上放置一个散列(引用),每次首先更改一个值
use warnings;
use strict;
use feature 'say';
use Data::Dump qw(dd);
# use Storable qw(dclone);
my %h = ( a => 1, b => 2 );
my @ary_w_refs;
for my $i (1..3) {
$h{a} = $i;
push @ary_w_refs, \%h; # almost certainly WRONG
# push @ary_w_refs, { %h }; # *copy* data
# push @ary_w_refs, dclone \%h; # may be necessary, or just safer
}
dd $_ for @ary_w_refs;
我使用Data::Dump用于显示复杂的数据结构,因其简单性和默认的紧凑输出。还有其他用于此目的的模块,Data::Dumper位于核心(已安装)。
以上打印
{ a => 3, b => 2 }{ a => 3, b => 2 }{ a => 3, b => 2 }
See how that value for key a
, that we changed in the hash each time, and so supposedly set for each array element, to a different value (1
, 2
, 3
) -- is the same in the end, and equal to the one we assigned last? (This appears to be the case in the question.)
This is because we assigned a reference to the hash %h
to each element, so even though every time through the loop we first change the value in the hash for that key in the end it's just the reference there, at each element, to that same hash.∗
So when the array is queried after the loop we can only get what is in the hash (at key a
it's the last assigned number, 3
). The array doesn't have its own data, only a pointer to hash's data.† (Thus hash's data can be changed by writing to the array as well, as seen in the example below.)
Most of the time, we want a separate, independent copy. Solution? Copy the data.
Naively, instead of
push @ary_w_refs, \%h;
我们能做到
push @ary_w_refs, { %h };
此处 {}
是匿名哈希的构造函数,‡ 因此内部的 %h
被复制。那么实际数据进入数组后一切都很好吗?在本例中,是的,其中哈希值是纯字符串/数字。
但是当哈希值本身是引用时怎么办?然后这些引用被复制,并且 @ary_w_refs
再次没有自己的数据!我们会遇到完全相同的问题。 (尝试上面的哈希值 ( a => [1..10] )
)
如果我们有一个复杂的数据结构,包含值的引用,我们需要一个深拷贝。一种好方法是使用库,并且 Storable其dclone
非常好
use Storable qw(dclone);
...
push @ary_w_refs, dclone \%h;
现在数组元素拥有自己的数据,与 %h
无关(但在复制时相等)。
对于简单的哈希/数组来说,这也是一件好事,可以避免将来的更改,即哈希已更改,但我们忘记了它被复制的位置(或者哈希及其副本没有更改)甚至互相了解)。
另一个例子。让我们用 hashref 填充一个数组,然后将其复制到另一个数组
use warnings;
use strict;
use feature 'say';
use Data::Dump qw(dd pp);
my %h = ( a => 1, b => 2 );
my @ary_src = \%h;
say "Source array: ", pp \@ary_src;
my @ary_tgt = $ary_src[0];
say "Target array: ", pp \@ary_tgt;
$h{a} = 10;
say "Target array: ", pp(\@ary_tgt), " (after hash change)";
$ary_src[0]{b} = 20;
say "Target array: ", pp(\@ary_tgt), " (after hash change)";
$ary_tgt[0]{a} = 100;
dd \%h;
(为了简单起见,我使用只有一个元素的数组。)
这会打印
Source array: [{ a => 1, b => 2 }]Target array: [{ a => 1, b => 2 }]Target array: [{ a => 10, b => 2 }] (after hash change)Target array: [{ a => 10, b => 20 }] (after hash change){ a => 100, b => 20 }
That "target" array, which supposedly was merely copied off of a source array, changes when the distant hash changes! And when its source array changes. Again, it is because a reference to the hash gets copied, first to one array and then to the other.
In order to get independent data copies, again, copy the data, each time. I'd again advise to be on the safe side and use Storable::dclone
(or an equivalent library of course), even with simple hashes and arrays.
Finally, note a slightly sinister last case -- writing to that array changes the hash! This (second-copied) array may be far removed from the hash, in a function (in another module) that the hash doesn't even know of. This kind of an error can be a source of really hidden bugs.
Now if you clarify where references get copied, with a more complete (simple) representation of your problem, we can offer a more specific remedy.
∗ An important way of using a reference that is correct, and which is often used, is when the structure taken the reference of is declared as a lexical variable every time through
for my $elem (@data) {
my %h = ...
...
push @results, \%h; # all good
}
每次都会重新引入词法 %h
,以便保留其在数组上的引用数据,因为数组在循环之外持续存在,对于每个元素都是独立的。
这样做的效率也更高,因为 %h
中的数据不会像 { %h }
那样被复制,而只是“重新调整用途”,也就是说,从在迭代结束时被销毁的词法 %h
到数组中的引用。
如果要复制的结构自然位于循环之外,这当然可能并不总是合适。然后使用它的深拷贝。
函数调用中也有同样的机制
sub some_func {
...
my %h = ...
...
return \%h; # good
}
my $hashref = some_func();
同样,当函数返回时,词法 %h
超出了范围,并且它不再存在,但它携带的数据和对它的引用被保留,因为它被返回并进行分配,使其引用计数非零。 (至少返回给调用者,也就是说;它可能在子执行过程中被传递到其他地方,所以我们可能仍然会遇到多个使用相同引用的 Actor 的困惑。)所以$hashref
具有对子中创建的数据的引用。
回想一下,如果一个函数被传递了一个引用,那么当它被调用时或在其执行期间(通过调用其他返回引用的子函数),更改并返回它,那么我们再次在某些调用者中更改了数据,可能会被远远删除从这部分程序流程来看。
当然,这种情况经常发生,因为数据池较大,不能一直复制,但是需要小心并组织代码(例如,尽可能模块化),以便最大限度地减少出错的可能性。
† 这是对“指针”一词的宽松使用,用于表示引用的作用,但如果要引用 C,我会说它有点“修饰” C指针
‡在不同的上下文中它可以是一个 block
关于arrays - 如何在 Perl 中正确替换哈希数组中的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69412285/
我的问题:非常具体。我正在尝试想出解析以下文本的最简单方法: ^^domain=domain_value^^version=version_value^^account_type=account_ty
好吧,这就是我的困境: 我正在为 Reddit 子版 block 开发常见问题解答机器人。我在 bool 逻辑方面遇到了麻烦,需要一双更有经验的眼睛(这是我在 Python 中的第一次冒险)。现在,该
它首先遍历所有 y 值,然后遍历所有 x 值。我需要 X 和 y 同时改变。 For x = 3 To lr + 1 For y = 2 To lr anyl.Cells(x, 1)
假设我有一个包含 2 列的 Excel 表格:单元格 A1 到 A10 中的日期和 B1 到 B10 中的值。 我想对五月日期的所有值求和。我有3种可能性: {=SUM((MONTH(A1:A10)=
如何转换 Z-score来自 Z-distribution (standard normal distribution, Gaussian distribution)到 p-value ?我还没有找到
我正在重写一些 Javascript 代码以在 Excel VBA 中工作。由于在这个网站上搜索,我已经设法翻译了几乎所有的 Javascript 代码!但是,有些代码我无法准确理解它在做什么。这是一
我遇到过包含日期格式的时间戳日期的情况。然后我想构建一个图表,显示“点击”项目的数量“每天”, //array declaration $array1 = array("Date" => 0); $a
我是scala的新手! 我的问题是,是否有包含成员的案例类 myItem:Option[String] 当我构造类时,我需要将字符串内容包装在: Option("some string") 要么 So
我正在用 PHP 创建一个登录系统。我需要用户使用他或她的用户名或电子邮件或电话号码登录然后使用密码。因为我知道在 Java 中我们会像 email==user^ username == user 这
我在 C++ 项目上使用 sqlite,但是当我在具有文本值的列上使用 WHERE 时出现问题 我创建了一个 sqlite 数据库: CREATE TABLE User( id INTEGER
当构造函数是显式时,它不用于隐式转换。在给定的代码片段中,构造函数被标记为 explicit。那为什么在 foo obj1(10.25); 情况下它可以工作,而在 foo obj2=10.25; 情况
我知道这是一个主观问题,所以如果需要关闭它,我深表歉意,但我觉得它经常出现,让我想知道是否普遍偏爱一种形式而不是另一种形式。 显然,最好的答案是“重构代码,这样你就不需要测试是否存在错误”,但有时没有
这两个 jQuery 选择器有什么区别? 以下是来自 w3schools.com 的定义: [attribute~=value] 选择器选择带有特定属性,其值包含特定字符串。 [attribute*=
为什么我们需要CSS [attribute|=value] Selector根本当 CSS3 [attribute*=value] Selector基本上完成相同的事情,浏览器兼容性几乎相似?是否存在
我正在解决 regx 问题。我已经有一个像这样的 regx [0-9]*([.][0-9]{2})。这是 amont 格式验证。现在,通过此验证,我想包括不应提供 0 金额。比如 10 是有效的,但
我正在研究计算机科学 A 考试的样题,但无法弄清楚为什么以下问题的正确答案是正确的。 考虑以下方法。 public static void mystery(List nums) { for (
好的,我正在编写一个 Perl 程序,它有一个我收集的值的哈希值(完全在一个完全独立的程序中)并提供给这个 Perl 脚本。这个散列是 (string,string) 的散列。 我想通过 3 种方式对
我有一个表数据如下,来自不同的表。仅当第三列具有值“债务”并且第一列(日期)具有最大值时,我才想从第四列中获取最大值。最终值基于 MAX(DATE) 而不是 MAX(PRICE)。所以用简单的语言来说
我有一个奇怪的情况,只有错误状态保存到数据库中。当“状态”应该为 true 时,我的查询仍然执行 false。 我有具有此功能的 Controller public function change_a
我有一个交易表(针对所需列进行了简化): id client_id value 1 1 200 2 2 150 3 1
我是一名优秀的程序员,十分优秀!