Perl 一种快速提取阵列相似数据的方法
我不知道如何在下面的问题中陈述我的问题,所以请容忍我 问题: 我有一个多维数组,如下所示:Perl 一种快速提取阵列相似数据的方法,perl,multidimensional-array,Perl,Multidimensional Array,我不知道如何在下面的问题中陈述我的问题,所以请容忍我 问题: 我有一个多维数组,如下所示: $raw_list[0]['123','foo','foo1','300'] $raw_list[1]['456','foo2','foo3','4'] $raw_list[2]['123','foo4','foo5','67'] $raw_list[3]['456','foo6','foo7','34'] my %raw_list; my $elt0 = '123'; my @rec = ('foo'
$raw_list[0]['123','foo','foo1','300']
$raw_list[1]['456','foo2','foo3','4']
$raw_list[2]['123','foo4','foo5','67']
$raw_list[3]['456','foo6','foo7','34']
my %raw_list;
my $elt0 = '123';
my @rec = ('foo', 'foo1', '300');
push @{$raw_list{$elt0}}, \@rec;
foreach my $elt0 (keys %raw_list) {
my $records = $raw_list{$elt0};
foreach my $rec (@$records) {
# Now $elt0 is (e.g.) '123'
# and $rec->[0] is 'foo', $rec->[1] is 'foo1', $rec->[2] is '300'
}
}
这通常会变得非常大(可能会达到上千个索引?)
我想用它来分隔$raw\u list[nth][0]中具有相同第0个元素值的所有记录,并对每个组进行操作,以便
$raw_list[0]['123','foo','foo1','300']
$raw_list[2]['123','foo4','foo5','67']
然后我对这个小组进行操作,以获得各种统计信息。例如,元素值“300”和“67”的总和,依此类推
当前解决方案:
目前,我的代码实际上就是这样的
my @anum_group = ();
@die_raw_list = sort {$a->[0] <=> $b->[0]} @die_raw_list;
my $anum_reference = @die_raw_list[0][0];
for my $row (0..$#die_raw_list)
{
if ($die_raw_list[$row][0] == $anum_reference)
{
push @anum_group, $die_raw_list[$row];
}
else
{
# Profile ANUM group
# ... operation to get statistical info on group here
# Initialize next ANUM group
$anum_reference = $die_raw_list[$row][0];
@anum_group = ();
push @anum_group, $die_raw_list[$row];
}
}
# Profile last ANUM group
# ... operation to get statistical info on group here
my@anum_group=();
@die_raw_list=排序{$a->[0]$b->[0]}@die_raw_list;
my$anum_reference=@die_raw_list[0][0];
对于我的$行(0..$#die#u raw_list)
{
if($die_raw_list[$row][0]==$anum_reference)
{
推送@anum_group,$die_raw_list[$row];
}
其他的
{
#阿努姆集团简介
#…在此获取组的统计信息的操作
#初始化下一个ANUM组
$anum_reference=$die_raw_list[$row][0];
@anum_组=();
推送@anum_group,$die_raw_list[$row];
}
}
#最后一个ANUM组简介
# ... 在此处获取组的统计信息的操作
最后的想法和问题:
我意识到,在非常大的数据上,这往往非常缓慢,我想加快速度
我是Perl新手,不知道如何最好地解决这个问题。一千个索引并不是那么多。。。是什么让你觉得你的代码很慢?什么部分比较慢
map($keys{$_->[0]} = 1, @raw_list);
foreach $k (keys %keys)
{
@a = grep($_->[0]==$k,@raw_list);
# do something with @a;
}
如果第一个元素如此重要,那么首先可以重新安排数据结构,以这种方式对其进行索引:
my %raw_list = ('123' => [['foo', 'foo1', '300'],
['foo4', 'foo5', '67']],
'456' => [['foo2', 'foo3', '4'],
['foo6', 'foo7', '34']]);
您可以动态构建它,如下所示:
$raw_list[0]['123','foo','foo1','300']
$raw_list[1]['456','foo2','foo3','4']
$raw_list[2]['123','foo4','foo5','67']
$raw_list[3]['456','foo6','foo7','34']
my %raw_list;
my $elt0 = '123';
my @rec = ('foo', 'foo1', '300');
push @{$raw_list{$elt0}}, \@rec;
foreach my $elt0 (keys %raw_list) {
my $records = $raw_list{$elt0};
foreach my $rec (@$records) {
# Now $elt0 is (e.g.) '123'
# and $rec->[0] is 'foo', $rec->[1] is 'foo1', $rec->[2] is '300'
}
}
然后像这样处理它:
$raw_list[0]['123','foo','foo1','300']
$raw_list[1]['456','foo2','foo3','4']
$raw_list[2]['123','foo4','foo5','67']
$raw_list[3]['456','foo6','foo7','34']
my %raw_list;
my $elt0 = '123';
my @rec = ('foo', 'foo1', '300');
push @{$raw_list{$elt0}}, \@rec;
foreach my $elt0 (keys %raw_list) {
my $records = $raw_list{$elt0};
foreach my $rec (@$records) {
# Now $elt0 is (e.g.) '123'
# and $rec->[0] is 'foo', $rec->[1] is 'foo1', $rec->[2] is '300'
}
}
要真正干净,您需要将所有这些封装在一个对象中…如果我理解正确,您需要获取第二维度第一个值中具有相同值的记录,在您的示例中,
123
,按其他字段对其排序,然后比较其中的某些值
这一切都可以通过按不同值排序来实现:
my @sorted = sort {
$a->[0] <=> $b->[0] || # <=> for numerical
$a->[1] cmp $b->[1] || # cmp for non-numerical
$a->[2] cmp $b->[2] ...etc
} @die_raw_list;
您可以将数据放入由第一个元素索引的哈希中,然后快速遍历哈希的每个元素:
#test data
my $foo = [[1,2,3],[1,5,6],[2,8,9]];
#group elements 1..n by first element
my %bar;
map { $bar{$_->[0]} ||= (); push(@{$bar{$_->[0]}},[@{$_}[1..@$_-1]]) } @$foo;
#lame dump
foreach (keys %bar) {
print "key: $_\n";
foreach (@{$bar{$_}}) {
foreach (@{$_}) {
print "$_ ";
}
print "\n";
}
print "\n";
}
当然,只有当您需要处理每个组,并且希望分别处理它们,并且可能需要多次传递时,此解决方案才有意义。这甚至比他当前的代码还要慢。His为O(n对数n);你的是O(n^2)(因为它会为每个键扫描列表一次)感谢大家提供了令人惊讶的解决方案。我现在就要尝试一下,然后带着结果回到这里。刚刚测试了下面的建议,我就成功了。再次感谢所有发表自己想法的人。:)不要在标题中写“已解决”。或者标签。或者谢谢!对不起,我不知道。无论如何,谢谢你指出这一点。我喜欢这个解决方案。我正在研究如何在我的代码中实现这一点。顺便说一句,我在这里处理的数据来自同一个程序中先前过滤的文本文件(目前通常在10~200mb左右)。进入$die_raw_列表的就是我需要的。尽管有问题。。。push_back是散列函数吗?好像在网上找不到。哎呀。我入侵Perl已经太久了。应该只是“推”。我已经修复了示例代码(并清理了一些语法)。