【问题标题】:Perl -> Avoiding unnecessary method callsPerl -> 避免不必要的方法调用
【发布时间】:2013-06-11 08:12:48
【问题描述】:

我必须阅读商店的日志文件。日志显示项目 ID 和后面的“已售”字样。所以我编写了一个脚本来读取这个文件,计算每个项目 id 出现的单词“sold”的次数。事实证明,这些物品有很多“所有者”。也就是说,“owner_id”(我的数据库中的数据)和“item_id”之间存在关系。我想知道所有者每天卖出多少物品,所以我创建了一个“%item_id_owner_map”:

my %item_id_sold_times;
my %item_id_owner_map;

open my $infile, "<", $file_location or die("$!: $file_location");
while (<$infile>) {
    if (/item_id:(\d+)\s*,\s*sold/) {
        my $item_id = $1;
        $item_id_sold_times{$item_id}++;
        my $owner_ids =
          Store::Model::Map::ItemOwnerMap->fetch_by_keys( [$item_id] )
          ->entry();
        for my $owner_id (@$owner_ids) {
            $item_id_owner_map{$owner_id}++;
        }
    }
}
close $infile;

“Store::Model::Map::ItemOwnerMap->fetch_by_keys([$item_id])->entry();”方法将 item_id 或 ids 作为输入,并返回 owner_id 作为输出。

一切看起来都很棒,但实际上,您会看到每次 Perl 找到一个正则表达式匹配项(即每次应用“if”条件时),我的脚本都会调用“Store::Model::Map::ItemOwnerMap- >fetch_by_keys”方法,非常昂贵,因为这些日志文件非常非常长。

有没有办法让我的脚本更有效率?如果可能,我只想调用我的 Model 方法一次。

最好的!

【问题讨论】:

  • 如果数据库上的SELECT 语句可以为您提供相同的信息,为什么还要解析日志文件?

标签: perl


【解决方案1】:

把你的逻辑分成两个循环:

while (<$infile>) {
    if (/item_id:(\d+)\s*,\s*sold/) {
        my $item_id = $1;
        $item_id_sold_times{$item_id}++;
    }
}
my @matched_items_ids = keys %item_id_sold_times;
my $owner_ids =
  Store::Model::Map::ItemOwnerMap->fetch_by_keys( \@matched_item_ids )
  ->entry();
for my $owner_id (@$owner_ids) {
    $item_id_owner_map{$owner_id}++;
}

我不知道entry() 调用是否正确,但该代码的一般形式应该适合您。

一般而言,数据库擅长获取行集,因此您可以尽量减少从数据库中获取的调用。

【讨论】:

  • 感谢代码完美运行,效率也提高了
猜你喜欢
  • 1970-01-01
  • 2022-08-09
  • 1970-01-01
  • 1970-01-01
  • 2022-08-03
  • 2017-03-08
  • 2021-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多