Быстрый способ извлечь аналогичные данные в массив - PullRequest
1 голос
/ 26 мая 2011

Я точно не знаю, как сформулировать мою проблему ниже в вопросе, поэтому, пожалуйста, потерпите меня.

Проблема:

У меня есть многомерный массив, который выглядит следующим образом:

$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']

Это обычно становится очень большим (может достигнуть более тысячи индексов?)

Я хочу разделить все записи с одинаковым значением 0-го элемента в $ raw_list [nth] [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 ]

2 голосов
/ 26 мая 2011

Тысяча индексов не так уж много ... Что заставляет вас думать, что ваш код работает медленно?А какая часть медленная?

Если первый элемент так важен, вы могли бы перестроить свою структуру данных, чтобы в первую очередь проиндексировать ее таким образом:

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 голос
/ 26 мая 2011

Вы можете поместить ваши данные в хеш, проиндексированный первым элементом, а затем быстро просмотреть каждый элемент хеша:

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

Конечно, это решение может иметь смысл только в том случае, если вам нужно обработать каждую группу, и вы хотите сделать их отдельно, и, возможно, потребуется сделать несколько проходов.

1 голос
/ 26 мая 2011

Если я вас правильно понимаю, вы хотите получить записи с одинаковым значением в первом значении во втором измерении, 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';
}
0 голосов
/ 26 мая 2011
map($keys{$_->[0]} = 1, @raw_list);
foreach $k (keys %keys)
{
 @a = grep($_->[0]==$k,@raw_list);
 # do something with @a;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...