【问题标题】:Why does my perl hash deform my array data?为什么我的 perl 哈希会变形我的数组数据?
【发布时间】:2013-06-15 09:00:12
【问题描述】:

我在 Perl 中遇到了一些有趣的行为,希望得到启发。 如您所见,我创建了一个名为@tuple 的数组,它有两个数组引用。当我将它分配给一个键并提取它时,我只得到与引用相对的第一个数组 VALUE。谁能告诉我为什么会这样?

my @VMstoreName = ($storeName[$i]);
my @VMdiskCap   = ($diskCap[$i]);
print "VMstoreName : ". join(' ', @VMstoreName) . "\n";
print "VMdiskCap : ". join(' ', @VMdiskCap) . "\n";
# Initializing our key
my @tuple =  (\@VMstoreName, \@VMdiskCap);
print "After tuple " . join(' ', @tuple) . "\n";

@virtualMachines{$vmNames[$i]} = @tuple;
my @DEBUG = @{$virtualMachines{$vmNames[$i]}};
print "After first map : " . join(' ', @DEBUG) . "\n";
print "WHAT??? $DEBUG[0] $DEBUG[1]!!!\n";

这是输出,我希望 After first map 的读取与 After tuple 完全一样

VMstoreName : 172.16.1.3:/export/Paul/test-0
VMdiskCap : 1   
After tuple ARRAY(0x2c4ccf0) ARRAY(0x2c4cd38)
After first map 172.16.1.3:/export/Paul/test-0
WHAT??? 172.16.1.3:/export/Paul/test-0 !!!

【问题讨论】:

  • 你期待什么?请提供预期的输出。此外,您的实际输出和您的代码不匹配:代码说 After hash,但输出 After first map?
  • 抱歉,我更正了打印错误,但我在上面说过,我希望 After first map 的行读取与 tuple 之后的完全一样

标签: perl


【解决方案1】:

你的问题从这里开始(我猜):

 @virtualMachines{$vmNames[$i]} = @tuple;

@hash{...} 是一个散列片:它一次访问散列中的多个条目(这可能只有一个条目)。切片作为 LHS 值强加列表上下文。

我们将@tuple 的值分配给这个列表。

现在列表赋值具有忘记多余值的特性:

my ($x, $y) = (1, 2, 3); # nobody likes № 3

所以上面的说法是一样的

$virtualMachines{ $vmNames[$i] } = $tuple[0];

具体来说,这会将数组引用分配给 %virtualMachines 条目,因为 @tuple 仅保存数组引用。

在下一行,您可以通过$virtualMachines{$vmNames[$i]} 访问此条目。这将评估为数组引用。然后您将其取消引用到带有@{ ... } 的数组。

这会将数组的所有值分配给@DEBUG,而不是数组引用。如您的调试语句所示,这是 VMstoreName。

解决方案

将数组引用分配给%virtualMachines 条目:

$virtualMachines{ $vmNames[$i] } = \@tuple;

数组和散列只能保存标量,所以我们不能使用数组作为值,只能数组引用

【讨论】:

    【解决方案2】:

    您正在使用相同的键在列表上下文中分配给您的哈希。键在哈希中必须是唯一的,因此只有一个引用存储在您的哈希中。 Hash-slice 只有 1 个元素宽,所以第二个引用会被忽略。

    您应该为@tuple 分配一个引用,而不是使用标量上下文:

    $virtualMachines{$vmNames[$i]} = \@tuple;
    

    【讨论】:

    • 谢谢,这正是我想要的。我不知道 perl 会这样砍掉价值!
    • @dakillakan 与my @x = (3, 4); my ($y) = @x;(实际上与my ($z) = (3, 4);)进行比较。 Perl 很乐意分配剩余的值,但您确实需要给它一个放置它们的位置。
    【解决方案3】:

    当您初始化@tuple 时,您正在传递对数组的引用。相反,只需传递数组:

    my @tuple = (@VMstoreName, @VMdiskCap);
    

    【讨论】:

      【解决方案4】:

      看起来@tuple 是一个数组引用数组。你必须尊重每个元素,才能按照你想要的方式打印出来。

      my @tuple =  (\@VMstoreName, \@VMdiskCap);
      print "After tuple " . join(' ', map { @$_ } @tuple) . "\n";
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-03-21
        • 2017-01-15
        • 1970-01-01
        • 1970-01-01
        • 2011-02-24
        • 2011-07-02
        • 1970-01-01
        相关资源
        最近更新 更多