3

考虑以下 HoH:

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

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

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

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

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

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

我能找到的最接近的语言结构是这里提到的智能匹配运算符 ( ~~)(在 perlref perldoc 中没有提到),但即使~~在 Perl 版本中可用,我也只能使用 (5.8.4),从什么我可以说它在这种情况下不起作用。

如果无法完成,我想我会在进入while循环之前将键复制到数组或散列中(这是我开始的方式),但我希望避免开销。

4

5 回答 5

3

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

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

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

然后你的exists($h->{*}->{1})变成exists($all{1}). 当然,如果您正在修改循环内的二级散列,这将不起作用(除非您进行了%all适当的更新)。该代码还假定其中的所有值$h都是 hashrefs,但如果需要,这很容易修复。

于 2011-11-08T23:55:06.937 回答
2

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

由于每个哈希都有自己的迭代器,因此您必须调用keys已在迭代的相同哈希each来遇到此问题。keys既然您调用该哈希没有问题,您可以简单地使用keys而不是each吗?或者也许调用keys一次,存储结果,然后遍历存储的键?

于 2011-11-09T05:56:31.120 回答
1

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

于 2011-11-09T01:18:39.640 回答
0

您是否尝试在没有任何 while 循环的情况下执行此操作?您可以通过引用它来测试哈希是否存在,而不会产生错误

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

}
于 2011-11-08T23:57:51.467 回答
-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 of 1 的 1 级键列表

于 2011-11-09T02:06:22.480 回答