繁体   English   中英

我如何使用“perl”中的“map”返回一个 hash 引用,其键是从一个数组引用中查找的,而该数组引用的值是从另一个数组中查找的?

[英]How can I use "map" in "perl" to return a hash reference whose key is looked up from an array reference whose value is looked up from another array?

我已经在 map 上搜索了其他许多 Stack 问题,但是这个要求很特殊,所以我可能无法完全找到我正在寻找的解决方案,或者我认为它确实存在。

这个问题只是关于性能。

作为有限的背景,此代码段用于解码传入令牌,因此它用于每个 web 请求,因此性能至关重要,我知道可以使用“地图”所以想使用它。

这是一个精简但仍然可以正常工作的代码段,我目前正在使用它并且运行良好:

use strict;
use Data::Dumper qw (Dumper);

my $api_token = { array => [ 'user_id', 'session_id', 'expiry' ], max => 3, name => 'session' };
my $token_got = [ 9923232345812112323, 1111323232000000465, 1002323001752323232 ];

my $rt;
for (my $i=0; $i<scalar @{$api_token->{array}}; $i++) {
  $rt->{$api_token->{array}->[$i]} = $token_got->[$i];
}

$rt->{type} = $api_token->{name};
print Dumper ($rt) . "\n";

问题是:就性能而言,复制上面的 foreach 语句的绝对最佳 PERL 代码是什么?

看起来你只需要一个 hash切片

my %rt;

@rt{ @{ $api_token->{array} } } = @$token_got;

或者,如果需要 hash 参考

my $rt;

@{ $rt } { @{ $api_token->{array} } } = @$token_got;

或者使用较新的后缀取消引用,在数组和 hash 切片上,也许更好一些

my $rt;

$rt->@{ $api_token->{array}->@* } = @$token_got;

也可以使用List::MoreUtils::mesh并在一个语句中完成

my $rt = { mesh @{ $api_token->{array} }, @$token_got };

或来自同一个库的成对

my $rt = { pairwise { $a, $b } @{ $api_token->{array} }, @$token_got };

这些 go 通过 C 代码如果库安装了List::MoreUtils::XS


对以上所有内容进行基准测试,使用问题中的微小数据集(虽然现实?),无论实现mesh / pairwise实现它们的速度都是其他实现的数倍

在装有 v5.26 的旧笔记本电脑上

              Rate use_pair use_mesh use_href use_post use_hash
use_pair  373639/s       --     -36%     -67%     -67%     -68%
use_mesh  580214/s      55%       --     -49%     -49%     -51%
use_href 1129422/s     202%      95%       --      -1%      -5%
use_post 1140634/s     205%      97%       1%       --      -4%
use_hash 1184835/s     217%     104%       5%       4%       --

在 v5.36 的服务器上,数字大约是pairwise160%--170%mesh比它快一点,与上面类似)

在其他方面,在笔记本电脑上,基于哈希的总是快几个百分点,而在 v5.36 的服务器上,它们都非常接近。 很容易称之为领带。


以下是由 OP 编辑的,他计算了 61% 的加速(见评论)

更改代码:

@rt{ @{ $api_token->{array} } } = @$token_got; ### much faster onliner replaced the loop. @zdim credit

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM