Perl 用数组引用替换标量散列值的更干净的存储方式?

Perl 用数组引用替换标量散列值的更干净的存储方式?,perl,hash,Perl,Hash,我正在构建一个散列,其中与标量关联的键不一定是唯一的。所需的行为是,如果键是唯一的,则值是标量。如果键不是唯一的,我希望该值是与键关联的标量的数组引用。因为散列是迭代建立的,所以我不知道密钥是否在时间之前是唯一的。现在,我正在做这样的事情: if(!defined($hash{$key})){ $hash{$key} = $val; } elseif(ref($hash{$key}) ne 'ARRAY'){ my @a; push(@a, $hash{$key}); p

我正在构建一个散列,其中与标量关联的键不一定是唯一的。所需的行为是,如果键是唯一的,则值是标量。如果键不是唯一的,我希望该值是与键关联的标量的数组引用。因为散列是迭代建立的,所以我不知道密钥是否在时间之前是唯一的。现在,我正在做这样的事情:

if(!defined($hash{$key})){
   $hash{$key} = $val;
}
elseif(ref($hash{$key}) ne 'ARRAY'){
   my @a;
   push(@a, $hash{$key});
   push(@, $val);
   $hash{$key} = \@a;
}
else{
   push(@{$hash{$key}}, $val);
}

有没有更简单的方法呢?

rjh很划算

if(!defined($hash{$key})){
    $hash{$key} = $val;
}
elsif (ref($hash{$key}) ne 'ARRAY') {
    $hash{$key} = [ $hash{$key}, $val ];
}
else{
   push(@{$hash{$key}}, $val);
}
我已经编写了太多代码,完全按照您所描述的做——哈希值是数组引用,除非它不是。Reams和Reams的条件类型检查。然后有一天我突然想到,“为什么我要写这些废话?只要到处使用数组引用,笨蛋。”我对自己说。从那天起,每当我在公园散步时,蓝知更鸟就会从树上飞下来给我唱歌

push @{$hash{$key}}, $val;
这就是你要做的。如果密钥不存在,则数组将自动激活

如果您不喜欢autoviv,并且希望明确,请执行以下操作:

$hash{$key} = [] unless exists $hash{$key};
push @{$hash{$key}}, $val;

即使这种“冗长”的方法也要短得多。

从可维护性和简单性的角度来看,假设所有键都是非唯一的,并使每个键都成为arrayref不是更容易吗?即使arrayref包含一个元素?翻译成更少的
if(ref$x eq'ARRAY')
到处都是样板。@rjh这是一个非常公平的观点。我需要考虑在我的特殊情况下,这将如何在更大的范围内发挥作用,但我同意这在总体上是有意义的。这与R处理事情的方式相似。这是更复杂的结构的一部分,重复的键是相当少见的。我会想一想。我是唯一一个能立刻想象出史莱克的地方吗?在那里,蓝鸟和菲奥娜唱歌,鸟儿爆炸了。哇,我不知道即使是arrayref解引用也会自动激活。所以我不再需要做
@{$hash{$key}| |=[]}
。。。整洁的这是一个老问题,但我很好奇为什么要使用arrayref?为什么不仅仅是hashref?@vol7ron,如果你想在你的hash中有多个值,你需要使用一种可以存储多个值的标量。这样就可以使用数组引用、哈希引用或某种序列化方案来管理倍数。根据您使用多个值的方式,使用散列而不是数组散列可能是有意义的。在本例中,OP询问有关标量或数组的散列。我建议使用一致的结构来节省复杂性。这个建议适用于您选择用来组成数据结构的任何元素。@daotoad:没错,我的意思是我已经做了HoA's,但是HoH可以被滥用来满足所有目的。我的意思是很容易创建一个
$hash->{$key}->{$index}='foo'
来服务多维数组的相同结构,其中index等于
$hash->{$key}
0
中的键数。如果顺序很重要,只需添加另一个维度:)我只是觉得HOH非常灵活,但同样,可能我滥用了它。您应该在第一个条件中使用
exists
——有可能
undef
会出现在
$hash{$key}
中,在这种情况下,您的最终条件会将其破坏。