Как этот Perl Sub может быть оптимизирован для скорости? - PullRequest
2 голосов
/ 09 августа 2011

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

Как можно оптимизировать этот perl sub для скорости?

Пример использования:

my @members;
...
$member= {};
$hash->{'name'}='James';
hpush('name', \@members,$member);

Подпункт:

sub hpush {
  # push a set of key value pairs onto an array as a hash, if the key doesn't already exist
  if (@_ != 3) {
    print STDERR "hpush requires 3 args, ".@_." given\n";
    return;
  }

  my $uniq = shift;
  my $rarray = shift;
  my $rhash = shift;
  my $hash = ();

  #print "\nHash:\n";
  for my $key ( keys %{$rhash} ) {
    my $valuea = $rhash->{$key};

    #print "key: $key\n";
    #print "key=>value: $key => $valuea\n";
    $hash->{ $key} = $valuea;
  }

  #print "\nCurrent Array:\n";
  for my $node (@{$rarray}) {
    #print "node: $node \n";
    for my $key ( keys %{$node} ) {
      my $valueb = $node->{$key};
      #print "key=>value: $key => $valueb\n";
      if ($key eq $uniq) {
        #print "key=>value: $key => $valueb\n";
        if (($valueb =~ m/^[0-9]+$/) && ($hash->{$key} == $valueb)) {
          #print "Not pushing i $key -> $valueb\n";
          return;
        } elsif ($hash->{$key} eq $valueb) {
          #print "Not pushing s $key -> $valueb\n";
          return;
        }
      }
    }
  }
  push @{$rarray}, $hash;
  #print "Pushed\n";

}

Обратите внимание, что Perl не мой, и я начинающий Perl

1 Ответ

10 голосов
/ 09 августа 2011

Этот код довольно ... не очень эффективен. Во-первых, он копирует $rhash в $hash с циклом for ... по какой-то причине. Затем он перебирает ключи хеша, вместо того, чтобы просто использовать ключ хеша, который ищет. Затем он выполняет две эквивалентные проверки, по-видимому, некоторые пытаются отличить числа от нечисловых и выбирают соответствующую проверку (== или eq). Это все ненужно.

Этот код ниже должен быть примерно эквивалентным. Я усердно урезал это. Это должно быть как можно быстрее.

use strict;
use warnings;

hpush('name', \@members,$member);

sub hpush { 
    my ($uniq, $rarray, $rhash) = @_;

    for my $node (@{$rarray}) {
        if (exists $node->{$uniq}) {
            return if ($node->{$uniq} eq $rhash->{$uniq});
        }
    }
    push @{$rarray}, $rhash;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...