当键和值都是数组引用时的 Perl 哈希

发布于 2024-12-12 08:29:21 字数 659 浏览 0 评论 0原文

我遇到一个问题,数字对映射到其他数字对。例如,(1,2)→(12,97)。有些对可能映射到多个其他对,所以我真正需要的是能够将一对映射到列表列表中,例如 (1,2)->((12,97),(4,1))。归根结底,我想单独处理每个值(即每个列表列表)。

在 Python 中,我可以通过简单地说:

key = ( x, y )
val = [ a, b ]
if (x,y) not in my_dict:
    my_dict[ (x,y) ] = []
my_dict[ (x,y) ].append( [a,b] )

但是,在 Perl 中,我必须对键和值使用 refs。所以我当然可以说:

$keyref = [ x1, y1 ]
$valref = [ a, b ]
%my_hash = { $keyref => $valref }

但是当另一对 (x2,y2) 出现时会发生什么?即使 x2==x1 和 y2==y1, $keyref=[x2,y2] 也会与之前生成的 keyref 不同,所以我看不到进行查找的方法。当然,我可以将 (x2,y2) 与每个取消引用的哈希键进行比较,但毕竟上帝给了我们哈希表,正是为了避免这样做的需要。

有 Perl 解决方案吗?

谢谢,

-W。

I have a problem where pairs of numbers map to other pairs of numbers. For instance, (1,2)->(12,97). Some pairs may map to multiple other pairs, so what I really need is the ability to map a pair into a list of lists, like (1,2)->((12,97),(4,1)). At the end of the day I want to process each of the values (i.e., each list of lists) separately.

In Python, I could do this by simply saying:

key = ( x, y )
val = [ a, b ]
if (x,y) not in my_dict:
    my_dict[ (x,y) ] = []
my_dict[ (x,y) ].append( [a,b] )

However, in Perl, I have to use refs for the keys and values. So I can certainly say:

$keyref = [ x1, y1 ]
$valref = [ a, b ]
%my_hash = { $keyref => $valref }

But what happens when another pair (x2,y2) comes along? Even if x2==x1 and y2==y1, $keyref=[x2,y2] will differ from the previous keyref generated, so I do not see a way to do the lookup. Of course, I could compare (x2,y2) with each dereferenced hash key, but after all, God gave us hash tables precisely to avoid the need to do so.

Is there a Perl solution?

Thanks,

-W.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半仙 2024-12-19 08:29:21

在 Perl 中,所有哈希键都是字符串,或者在查找之前“字符串化”。使用数组引用作为键通常是错误的方法。

使用“二维”哈希怎么样?

$hash{$x1}{$y1} = [ $a, $b ];
# or
%hash = ( $x1 => { $y1 => [ $a, $b ] } );


($x2,$y2)=($x1,$y1);
print @{$hash{$x2}{$y2}};   # will print $a and $b

In Perl, all hash keys are strings, or are "stringified" before lookup. Using an array reference as a key is usually the wrong approach.

What about using a "two-dimensional" hash?

$hash{$x1}{$y1} = [ $a, $b ];
# or
%hash = ( $x1 => { $y1 => [ $a, $b ] } );


($x2,$y2)=($x1,$y1);
print @{$hash{$x2}{$y2}};   # will print $a and $b
幸福不弃 2024-12-19 08:29:21

与 Perl 中的大多数内容一样,TMTOWTDI

选项 1:使用多维数组模拟

$hash{$x,$y} = [$a, $b];

另请参阅内置变量的文档 <代码>$;

选项 2:使用 Hash::MultiKey 模块

tie %hash, 'Hash::MultiKey';
$hash{[$x, $y]} = [$a, $b];

选项 3:使用 HoH(哈希值的哈希值)

$hash{$x}{$y} = [$a, $b];

Like most things in Perl, TMTOWTDI.

Option 1: Use multidimensional array emulation

$hash{$x,$y} = [$a, $b];

See also the documentation for the built-in variable $;.

Option 2: Use the Hash::MultiKey module

tie %hash, 'Hash::MultiKey';
$hash{[$x, $y]} = [$a, $b];

Option 3: Use a HoH (hash of hashes) instead

$hash{$x}{$y} = [$a, $b];
财迷小姐 2024-12-19 08:29:21

我最终使用了 Socket Puppet 的解决方案(以 Michael Carmen 的选项 3 的形式)。仅供参考,这里有一个小 Perl 脚本,它执行我的应用程序中所需的所有操作。

打印的第 2:,3: 和 4:,5: 只是使用不同的语法来做同样的事情,而第 0: 和 1: 行只是为了一路进行健全性检查。

这添加到建议的解决方案中的是使用数组数组作为与键一起使用的值。

@k1 = ( 12, 13 );
$aref = [ 11, 22 ];
$bref = [ 33, 44 ];
%h = {};
if( not exists $h{$k1[0]}{$k1[1]} ) {
    print "initializing\n";
    $h{$k1[0]}{$k1[1]} = [];
}
push @{$h{$k1[0]}{$k1[1]}}, $aref;
push @{$h{$k1[0]}{$k1[1]}}, $bref;
print "0: ", join ':', @{$h{$k1[0]}{$k1[1]}}, "\n";
print "1: ", join ':', ${$h{$k1[0]}{$k1[1]}}[0], "\n";
print "2: ", join ':', @{${$h{$k1[0]}{$k1[1]}}[0]}, "\n";
print "3: ", join ':', @{${$h{$k1[0]}{$k1[1]}}[1]}, "\n";
print "4: ", join ':', @{$h{$k1[0]}{$k1[1]}->[0]}, "\n";
print "5: ", join ':', @{$h{$k1[0]}{$k1[1]}->[1]}, "\n";

PS 我本想将其添加为评论,但它太长了,我认为包含一个有效的示例是有意义的。

I ended up using Socket Puppet's solution (in the form of Michael Carmen's Option 3). FYI, here is a little Perl script that carries out all the operations I need in my app.

Printed lines 2:,3: and 4:,5: just use different syntax to do the same thing, and lines 0: and 1: were just intended as sanity checks along the way.

What this this adds to the suggested solution is the use of an array of arrays as the value that goes along with a key.

@k1 = ( 12, 13 );
$aref = [ 11, 22 ];
$bref = [ 33, 44 ];
%h = {};
if( not exists $h{$k1[0]}{$k1[1]} ) {
    print "initializing\n";
    $h{$k1[0]}{$k1[1]} = [];
}
push @{$h{$k1[0]}{$k1[1]}}, $aref;
push @{$h{$k1[0]}{$k1[1]}}, $bref;
print "0: ", join ':', @{$h{$k1[0]}{$k1[1]}}, "\n";
print "1: ", join ':', ${$h{$k1[0]}{$k1[1]}}[0], "\n";
print "2: ", join ':', @{${$h{$k1[0]}{$k1[1]}}[0]}, "\n";
print "3: ", join ':', @{${$h{$k1[0]}{$k1[1]}}[1]}, "\n";
print "4: ", join ':', @{$h{$k1[0]}{$k1[1]}->[0]}, "\n";
print "5: ", join ':', @{$h{$k1[0]}{$k1[1]}->[1]}, "\n";

P.S. I would have added this as a comment but it was too long, and I thought it made sense to include a worked example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文