2010-10-29 18 views
7

Perl newbie. Bir foreach döngüsü sırasında bir değişkenin birkaç değerle yüklendiği bir kodum var. Benim yapmak istediğim, o değişkende bazı işlemleri sadece bu dizide olması durumunda gerçekleştirmektir. en verimli nedir yolu üzerinde çalışıyorum veri olarak perl olarak çok büyüktür.Perl: Bir değişkenin değerinin bir dizideki değerle eşleşip eşleşmediğini bulmak

Soruma basit bir örnek, ben

@fruits_i_like = qw (mango banana apple); 

istiyorum meyvelerden bir dizi var sürüyorlar Ama bir veri dosyasından meyvelerin adını alan bir foreach döngüsünde bir $ meyve değişkeni olduğunu tüm farklı meyve türlerine sahiptir. Sadece #fruits_i_like dizimdeki $ meyve durumlarını nasıl seçerim?

+1

'Geniş' ne kadar büyük? – Zaid

+0

iyi okumam gereken dosya yaklaşık 50MB. – sfactor

+0

@sfactor: O zaman o kadar da kötü değil. – Zaid

cevap

10

: Burada

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

mfontani çözümü

vs bu şekilde karşılaştırmak bir kriter
#!/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 
     } 
    }, 
}); 

Çıkış:

  Rate grep hash 
grep 1074911/s -- -76% 
hash 4392945/s 309% -- 
+1

'sub {}' ile 'q {}' arasında değiştirin ve bu karşılaştırmayı tekrar çalıştırın. Alt rutin çağrı ek yükü sayıları çok fazla değiştirebilir. – tchrist

+3

Sadece bu amaç için% h oluşturuyorsanız, bu karşılaştırmanın bir parçası olmamalıdır? –

+3

@ Øyvind Skaar: Öyle düşünmüyorum çünkü OP, meyveleri birçok kez eşleştirmek istiyor. % h yalnızca bir kez oluşturulur ve birçok kez kullanılır.Her farklı meyve için grepin yapıldığı grep çözümünden farklıdır. – Toto

11

Perl 5.10 veya üstü?

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 önce:

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

olumsuz bütün dizi eşleşmeleri belirlemek üzere ayrıştırılır olmasıdır. Bu en iyi seçenek olmayabilir, bu durumda List::MoreUtils 'any()'u kullanabilirsiniz, bu değer bir değerle eşleştikten sonra döndürür ve diziden geçmeye devam etmez.

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

Happy hacking!

9

Bu, etkin bir şekilde bir arama sorundur. @fruits_i_like değerlerini %fruits_i_like (bir dizinin O (1) ve O (n) 'si gibi) içinde bulmak daha hızlı olacaktır.

aşağıdaki işlemi kullanarak bir karma dizi dönüştürme: Böyle bir karma kullanabilirsiniz

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 
} 
İlgili konular