2009-06-16 16 views
42

Metin dosyasındaki çeşitli dizelerin tekrar sayısını belirten bir Perl betiğim var. Belirli bir dizenin henüz hashta bir anahtar olup olmadığını kontrol edebilmek istiyorum. Bunu daha iyi yapmanın daha iyi bir yolu var mı? İşte Perl hash'ın zaten bir anahtarının olup olmadığını nasıl görebilirim?

yapıyorum budur:

foreach $line (@lines){ 
    if(($line =~ m|my regex|)) 
    { 
     $string = $1; 
     if ($string is not a key in %strings) # "strings" is an associative array 
     { 
      $strings{$string} = 1; 
     } 
     else 
     { 
      $n = ($strings{$string}); 
      $strings{$string} = $n +1; 
     } 
    } 
} 
+4

Sorun şu ki, neden bununla uğraşmıyorsunuz? Eğer mevcut değilse, $ n undef olacaktır. Undef'in sayısal değeri 0, yani $ n + 1 = 1. Başlangıçta karma olup olmadığını kontrol etmeye gerek yok. –

cevap

95

Bir anahtar bir karma olup olmadığını kontrol etmek inanmak Ben bu kod sorunuza cevap gerektiğini tahmin

if (exists $strings{$string}) { 
    ... 
} else { 
    ... 
} 
+13

Perl'in, son hash'ta aradığınız anahtarın mevcut olup olmadığını "kontrol etmek" için çok boyutlu bir karmada bulunmayan herhangi bir ara anahtarın otomatik olarak işleneceğini unutmayın. Bu örnek gibi basit bir karma ile ilgili bir sorun değil ama ..% sınama =(); print "bar" ise ($ test {'foo'} {'bar'} var); # perl, "foo var şimdi ve siz bunu beklemiyor olabilirsiniz" çubuğuna bakmak için sadece foo tuşunu otomatik olarak yedeklediniz. eğer ($ test {'foo'} var); – Drew

6

sadece yapın:

use strict; 
use warnings; 

my @keys = qw/one two three two/; 
my %hash; 
for my $key (@keys) 
{ 
    $hash{$key}++; 
} 

for my $key (keys %hash) 
{ 
    print "$key: ", $hash{$key}, "\n"; 
} 

Çıktı:

(. perlvar içinde $_ Bkz)

$hash{$_}++ for (@keys); 

Ve hatta böyle bir şey yazabilirsiniz:: 10

three: 1 
one: 1 
two: 2 

yineleme basitleştiirlebilir öyle her anahtar ilk kez bildiriyor

$hash{$_}++ or print "Found new value: $_.\n" for (@keys); 

buldum. değeri yoksa operatör 0 olmasını üstlenecek ++,

foreach $line (@lines){ 
     $strings{$1}++ if $line =~ m|my regex|; 
} 

:

+0

Evet, önemli olan, anahtarların ne olacağını önceden bilmem. –

+1

Evet, bu amaç için anahtarın varlığını kontrol etmeniz gerekmez. Basitçe $ dizeleri {$ 1} ++. Anahtar orada değilse, undef ile değer olarak eklenecektir, ++ sizin için 0 olarak yorumlanacaktır. – Arkadiy

+0

Elbette. Asıl nokta, döngünüzün tüm gövdesini (if altında) $ dizeleri {$ 1} ++ ile değiştirebilmenizdir. – zoul

-1

Sadece gidebilirsiniz:

if(!$strings{$string}) .... 
+0

Evet, bu da işe yarıyor. Teşekkürler! –

+7

Bu, yalnızca tüm anahtarların yanlış olmayan değerlere sahip olması durumunda çalışır. Genel olarak, bu kötü bir varsayımdır. Sadece bunun için özel olarak tasarlanmış var() kullanın. –

+2

@brian de foy - Ah ha. Cevap vermemem gerektiğini biliyordum :-) –

9

Eh, bütün kod sınırlandırılabilir (ve sonra 1'e kadar artırın). Zaten orada ise - sadece artırılır.

+0

Cevabınız doğru olsa da, karmalarla ilgili soruyu yanıtlıyor. – Chris

9

if ($hash{$key})'u kullanmayla ilgili olarak, anahtar varsa, ancak değeri sıfır veya boş olduğunda beklediğiniz şeyi yapmayacağından dolayı size tavsiyede bulunacağım.

+1

Bu belirli durumlar yalnızca iç içe geçmiş anahtarlar içindir. Bu problem için var olan cevaptır. Bir çekimde yuvalanmış tuşlar için kullanmayın. –

+1

Downvote hala biraz zor olsa da - bu sorudaki betiğin sadeliği ile uyarı geçersiz hale getirilmiyor. Daha önemlisi, ne tanımlanmış ne de var olan ($ hash {$ key}) kullanımının “sıfır, fakat doğru” problemi olduğu konusudur. – RET

+0

"Sıfır ama gerçek" şey bir oy hakkı hak ediyor. Ama oto-otomatikleştirme hakkında söylediğin şey basitçe yanlış ve bir düşüşü hak ediyor. – innaM

İlgili konular