Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 一种快速提取阵列相似数据的方法_Perl_Multidimensional Array - Fatal编程技术网

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已经太久了。应该只是“推”。我已经修复了示例代码(并清理了一些语法)。