我不知道如何在下面的问题中陈述我的问题,所以请耐心等待。
问题:
我有一个看起来像这样的多维数组:
$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']
这通常会变得非常大(可能会超过1000个索引?)
我想用它来分隔$raw_list[nth][0]中具有相同第0个元素值的所有记录,并对每个组进行操作,以便。。。
$raw_list[0]['123','foo','foo1','300']
$raw_list[2]['123','foo4','foo5','67']
然后我对这个小组进行操作,以获得各种统计信息。例如,元素值"300"one_answers"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
最后的想法和问题:
我意识到,在非常大的数据上,这往往非常缓慢,我想加快速度。
我是Perl新手,不知道如何最好地解决这个问题。
一千个索引并不是那么多。。。是什么让你认为你的代码很慢?什么部分比较慢?
如果第一个元素如此重要,您可以重新安排您的数据结构,以便首先对其进行索引:
my %raw_list = ('123' => [['foo', 'foo1', '300'],
['foo4', 'foo5', '67']],
'456' => [['foo2', 'foo3', '4'],
['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;
然后,您可以简单地循环浏览数据,挑选出您需要的值。
如果你只想要一些值,你可以用一些简单的东西来进行部分选择,比如:
my @partial;
for my $refs (@die_raw_list) {
push @partial, $ref if $ref->[0] == '123';
}
您可以将数据放入由第一个元素索引的哈希中,然后快速遍历哈希的每个元素:
#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";
}
当然,只有当您需要处理每个组,并希望分别处理它们,并且可能需要多次通过时,此解决方案才有意义。
map($keys{$_->[0]} = 1, @raw_list);
foreach $k (keys %keys)
{
@a = grep($_->[0]==$k,@raw_list);
# do something with @a;
}