在不使用keys()的情况下访问Perl HoH中的嵌套哈希?

时间:2011-11-08 23:29:52

标签: perl hash-of-hashes

考虑以下问题:

$h = {
    a => {
           1 => x
    },
    b => {
           2 => y
    },
    ...
}

有没有办法在不调用keys(%$h)的情况下检查第二个嵌套级别上是否存在哈希键?例如,我想说的是:

if ( exists($h->{*}->{1}) ) { ...

(我意识到你不能使用*作为哈希键通配符,但是你明白了......)

我正在尝试避免使用keys(),因为它会重置哈希迭代器,并且我在循环中使用以下代码$h进行迭代:

while ( (my ($key, $value) = each %$h) ) {
    ...
}

我能找到的最接近的语言构造是smart match operator (~~) mentioned here(并且在perlref perldoc中没有提到),但即使在Perl版本中~~可用,我也被限制使用(5.8 .4),从我可以说它在这种情况下不起作用。

如果无法完成,我想我会在进入while循环之前将密钥复制到数组或哈希中(这就是我的开始),但我希望避免开销。 / p>

5 个答案:

答案 0 :(得分:3)

不是真的。如果你需要这样做,我想我会创建一个合并的哈希,列出所有二级密钥(在开始你的主循环之前):

my $h = {
    a => {
           1 => 'x'
    },
    b => {
           2 => 'y'
    },
};

my %all = map { %$_ } values %$h;

然后您的exists($h->{*}->{1})变为exists($all{1})。当然,如果你在循环中修改二级哈希值,这将不起作用(除非你适当地更新%all)。该代码还假设$h中的所有值都是hashrefs,但如果需要,这很容易修复。

答案 1 :(得分:2)

没有。 each使用哈希的迭代器,你不能在不使用迭代器的情况下迭代哈希,即使在C API中也是如此。 (这意味着智能匹配无论如何也无济于事。)

由于每个哈希都有自己的迭代器,因此必须在使用keys迭代的相同哈希上调用each才能遇到此问题。既然您在该哈希上调用keys没有问题,那么您只需使用keys代替each吗?或者可以调用keys一次,存储结果,然后迭代存储的密钥?

答案 2 :(得分:1)

您几乎肯定会发现聚合二级哈希的“开销”小于任何其他解决方案的“开销”。每次要进行检查时,简单的哈希查找比遍历整个数据结构要快得多。

答案 3 :(得分:0)

你试图在没有任何while循环的情况下这样做吗?您可以仅通过引用来测试哈希中的存在,而不会生成错误

while (  my ($key, $value) = each %{$h} ) {
    if ($value->{1}) { .. } 

}

答案 4 :(得分:-1)

为什么不在Sybase本身而不是Perl中执行此操作?

您正在尝试进行集合操作,这是Sybase首先要构建的。

假设您从表中检索了数据“key1”,“key2”,“valye”为“select *”的数据,只需执行以下操作:

-- Make sure mytable has index on key1
SELECT key1
FRIN mytable t1
WHERE NOT EXISTS (
    SELECT 1 FROM mytable t2
    WHERE t1.key1=t2.key1
    AND t2.key2 = 1
)

-----------
-- OR
-----------

SELECT DISTINCT key1
INTO   #t
FROM   mytable

CREATE INDEX idx1_t on #t (key1)

DELETE #t
FROM   mytable
WHERE #t.key1=mytable.key1
AND   mytable.key2 = 1

SELECT key1 from #t    

任一查询都返回一个没有key2为1的第一级密钥列表