Perl: найти, если значение переменной совпадает со значением в массиве - PullRequest
7 голосов
/ 29 октября 2010

Я новичок в Perl.У меня есть код, в котором переменная загружается с несколькими значениями во время цикла foreach.То, что я хочу сделать, это выполнить некоторые операции с этой переменной, только если она находится в этом массивеКаков самый эффективный способ сделать это в Perl, поскольку данные, над которыми я работаю, очень велики.

Простой пример моего вопроса: скажем, у меня есть множество фруктов, которые яwant

@fruits_i_like = qw (mango banana apple);

Но у меня есть переменная $ fruit в цикле foreach, которая получает название фруктов из файла данных, который содержит все различные типы фруктов.Как выбрать только те случаи $ fruit, которые есть в моем массиве @fruits_i_like?

Ответы [ 3 ]

11 голосов
/ 29 октября 2010

Perl 5.10 или выше?

use strict;
use warnings;
use 5.10.0;
my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
if ( $this_fruit ~~ \@fruits_i_like ) {
     say "yummy, I like $this_fruit!";
}

До 5.10:

use strict;
use warnings;
my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
if ( scalar grep $this_fruit eq $_, @fruits_i_like ) {
     print "yummy, I like $this_fruit!\n";
}

Недостатком является то, что массив whole анализируется для поиска совпадений. Это может быть не лучшим вариантом, и в этом случае вы можете использовать List::MoreUtils 'any(), который возвращает true, когда совпадает со значением, и не продолжает проходить через массив.

use strict;
use warnings;
use List::MoreUtils qw/any/;
my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
if ( any { $this_fruit eq $_ } @fruits_i_like ) {
     print "yummy, I like $this_fruit!\n";
}

Счастливого взлома!

10 голосов
/ 29 октября 2010

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

my %h = map {$_ => 1 } @fruits_i_like;
if (exists $h{$this_fruit}) {
    # do stuff
}

Вот пример, который сравнивает этот способ с решением mfontani

#!/usr/bin/perl 
use warnings;
use strict;
use Benchmark qw(:all);

my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
my %h = map {$_ => 1 } @fruits_i_like;
my $count = -3;
my $r = cmpthese($count, {
    'grep' => sub {
         if ( scalar grep $this_fruit eq $_, @fruits_i_like ) {
             # do stuff
         }
    },
    'hash' => sub {
        if (exists $h{$this_fruit}) {
             # do stuff
        }
    },
});

Вывод:

          Rate grep hash
grep 1074911/s   -- -76%
hash 4392945/s 309%   --
9 голосов
/ 29 октября 2010

Это проблема поиска. Было бы быстрее искать значения @fruits_i_like в хэше, например %fruits_i_like (который равен O (1) против O (n) массива).

Преобразовать массив в хеш, используя следующую операцию:

open my $data, '<', 'someBigDataFile.dat' or die "Unable to open file: $!";

my %wantedFruits;
@wantedFruits{@fruits_i_like} = ();  # All fruits_i_like entries are now keys

while (my $fruit = <$data>) {        # Iterates over data file line-by-line

     next unless exists $wantedFruits{$fruit};  # Go to next entry unless wanted

     # ... code will reach this point only if you have your wanted fruit
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...