一种快速提取数组中相似数据的方法

时间:2011-05-26 01:20:52

标签: 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']

这通常会非常大(可能会超过一千个索引?)

我想要做的是将所有记录与 $ raw_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

最后的想法和问题:

我意识到在非常大的数据上,这往往非常慢,我想加快速度。

我是Perl的新手,不知道如何最好地解决这个问题。

4 个答案:

答案 0 :(得分:2)

一千个索引并不是那么多......是什么让你觉得你的代码很慢?什么部分很慢?

如果第一个元素很重要,您可以重新安排数据结构,以便首先将其编入索引:

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'
    }
}

要真的很干净,你可能希望将所有这些封装在一个对象中......

答案 1 :(得分:1)

如果我理解正确,您希望获取第二维中第一个值中相同值的记录,在示例中为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';
}

答案 2 :(得分:1)

您可以将数据放入由第一个元素索引的哈希中,然后快速浏览哈希的每个元素:

#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";
}

当然,这个解决方案可能只有在您需要处理每个组时才有意义,并且希望单独进行,并且可能需要进行多次传递。

答案 3 :(得分:-2)

map($keys{$_->[0]} = 1, @raw_list);
foreach $k (keys %keys)
{
 @a = grep($_->[0]==$k,@raw_list);
 # do something with @a;
}