【问题标题】:perl better method for counting each array element occuranceperl 更好的方法来计算每个数组元素的出现次数
【发布时间】:2018-09-19 07:16:16
【问题描述】:

我有 2 个数组,一个是根数组,其中包含大量元素。另一个是测试数组,所有元素都是根数组的子集。我想构造一个新数组,大小等于根数组,它在特定位置的元素值代表被测数组中该元素的计数。

当 2 数组大小较小时,以下代码效果很好。但是我遇到的实际问题是,根数组大约有 15000 个元素,而测试的数组大约有 14000 个。
我想知道有更好的算法。你们有什么建议吗?

my @root=qw(1 2 3 4 5 6 7 8 10);
my @aa=qw(1 1 2 3);
my @count;

foreach my $eleroot(@root){
my $mathnum=0;
my ($i) = grep { $root[$_] ~~ $eleroot } 0 .. $#root;
foreach my $eleaa(@aa){
 if ($eleroot==$eleaa){
  $mathnum++;
   }
 }
 $count[$i]=$mathnum;

}
print @count;

【问题讨论】:

  • 如果您甚至不尝试自己编写解决方案,您将不会得到满意的答案。
  • 这些值不是频率:它们是简单的计数。
  • 继续尝试解决方案,然后我们很乐意为您提供改进代码的建议。一种解决方案可能会使用散列散列来保存数据,其中“id”作为外部散列的键,列号被视为内部散列的键。喜欢$seen{$id}{$col}++。见this example
  • 感谢您的好意建议。我已经尝试了大约 8 个小时并得到它。但是当数组数量和大小增加时就不好了。希望与您讨论
  • 请不要使用损坏的、实验性的~~ 运算符。

标签: perl machine-learning svm


【解决方案1】:

更好的算法是使用散列来保持计数。对于您的示例数组,它看起来像这样。 (并且运行速度比您的解决方案快得多)。

#!/usr/bin/perl
use strict;
use warnings;

my @root=qw(1 2 3 4 5 6 7 8 10);
my @aa=qw(1 1 2 3);

print join("\t", @root), "\n";

my %seen;
for my $data (@aa) {
    $seen{$data}++; 
}

print join("\t", map {$_ // '0'} @seen{@root}), "\n";   

输出是:

1       2       3       4       5       6       7       8       10
2       1       1       0       0       0       0       0       0

@seen{@root} 是一个以@root 数组为键的散列片。如果没有找到任何 @root 元素的项目,则地图提供零。

map {$_ // '0'} 部分表示如果 $_ 有计数则传递给 join 计数,否则传递零。

【讨论】:

  • 不错!为了简单计数,我还喜欢将 for 循环压缩成一行:$seen{$_}++ for @aa
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-20
  • 1970-01-01
  • 2017-08-28
  • 2020-08-12
  • 2022-11-30
相关资源
最近更新 更多