Bir Perl karma anahtarları arasında yineleme için en güvenli yolu nedir?

oy
84

Ben (anahtar, değer) çiftleri bir grup ile bir Perl karma varsa, bütün anahtarların yineleme tercih edilen yöntem nedir? Ben kullanarak duymuş eachbir şekilde Mayıs yan etkileri üzerindeki istenmeyen. Yani, bu doğrudur ve aşağıdaki iki yöntemden en iyilerinden biridir, ya da daha iyi bir yolu vardır?

# Method 1
while (my ($key, $value) = each(%hash)) {
    # Something
}

# Method 2
foreach my $key (keys(%hash)) {
    # Something
}
Oluştur 06/08/2008 saat 03:53
kaynak kullanıcı
Diğer dillerde...                            


9 cevaplar

oy
170

Temel kural ihtiyaçlarınıza en uygun işlevini kullanmaktır.

Sadece anahtarlarını istiyorum ve hiç düşünmüyorsanız okunan değerlerden herhangi tuşlarını kullanın ():

foreach my $key (keys %hash) { ... }

Sadece değerleri isterseniz,) (değerleri kullanmak:

foreach my $val (values %hash) { ... }

Eğer anahtarları gerekiyorsa ve değerlerini, her () kullanın:

keys %hash; # reset the internal iterator so a prior each() doesn't affect the loop
while(my($k, $v) = each %hash) { ... }

Eğer herhangi bir şekilde karma anahtarlarını değiştirmeyi planlıyorsanız dışında yineleme sırasında akım anahtarı silmek için, o zaman her kullanmamalısınız (). Örneğin, iki katına değerlerle büyük tuşların yeni bir dizi oluşturmak için bu kodu) (tuşlarını kullanarak çalışıyor:

%h = (a => 1, b => 2);

foreach my $k (keys %h)
{
  $h{uc $k} = $h{$k} * 2;
}

beklenen elde edilen karma üretilmesi:

(a => 1, A => 2, b => 2, B => 4)

Fakat her kullanılarak () aynı şeyi yapmak için:

%h = (a => 1, b => 2);

keys %h;
while(my($k, $v) = each %h)
{
  $h{uc $k} = $h{$k} * 2; # BAD IDEA!
}

Sert-tahmin etmek şekillerde yanlış sonuçlar üretir. Örneğin:

(a => 1, A => 2, b => 2, B => 8)

Ancak bu, güvenlidir:

keys %h;
while(my($k, $v) = each %h)
{
  if(...)
  {
    delete $h{$k}; # This is safe
  }
}

Tüm bu perl belgelerinde açıklanmıştır:

% perldoc -f keys
% perldoc -f each
Cevap 06/08/2008 saat 14:22
kaynak kullanıcı

oy
21

Eğer kullanırken bilmeniz gereken bir şey eacho (hash "sonraki" tuşuna ne hatırlamak mevcuttur) için karma "devlet" ekleyerek yan etkiye sahip olmasıdır. Tek seferde bütün karma üzerinde yineleme yukarıda yayınlanan snippet'lar gibi kod kullanarak, bu genellikle bir sorun değildir. Ancak, sorunları izini sert içine çalışacaktır (tecrübe konuşuyor;) kullanırken eachgibi tablolarla birlikte lastya da returnçıkmak için while ... eachtüm anahtarları işledik önce döngü.

Bu durumda, karma zaten geri döndü hangi tuşları hatırlar ve kullandığınız zaman each(belki bir kod toplam ilgisiz parça halinde) üzerinde bir dahaki sefere, bu pozisyonda devam edecektir.

Örnek:

my %hash = ( foo => 1, bar => 2, baz => 3, quux => 4 );

# find key 'baz'
while ( my ($k, $v) = each %hash ) {
    print "found key $k\n";
    last if $k eq 'baz'; # found it!
}

# later ...

print "the hash contains:\n";

# iterate over all keys:
while ( my ($k, $v) = each %hash ) {
    print "$k => $v\n";
}

Bu baskılar:

found key bar
found key baz
the hash contains:
quux => 4
foo => 1

Ne tuşları "bar" ve baz "? Onlar hala orada, ama ikinci oldu eachİlki bıraktığı ve karma sonuna ulaştığında durur başlar, bu yüzden ikinci döngüde görmem.

Cevap 16/09/2008 saat 00:37
kaynak kullanıcı

oy
19

Yer eachsize sorunlara neden olabilir gerçek bir sigara kapsamına sahip yineleyici olmasıdır. Örnek olarak:

while ( my ($key,$val) = each %a_hash ) {
    print "$key => $val\n";
    last if $val; #exits loop when $val is true
}

# but "each" hasn't reset!!
while ( my ($key,$val) = each %a_hash ) {
    # continues where the last loop left off
    print "$key => $val\n";
}

Eğer emin olmak gerekirse eachtüm anahtarları ve değerleri alır, kullandığınız emin olmak gerekir keysya da values(o yineleyici sıfırlar gibi) ilk. Bkz her belgelerine .

Cevap 16/09/2008 saat 15:35
kaynak kullanıcı

oy
13

Her sözdizimi kullanarak tek seferde üretilen gelen anahtarları kümesinin tamamını önleyecektir. Eğer satırlar milyonlarca bir veritabanına tie-ed karma kullanıyorsanız bu önemli olabilir. Tek seferde anahtarların tüm listeyi oluşturmak ve fiziksel belleği tüketmesine istemiyoruz. döngü başlamadan önce şifreler ise bir yineleyici aslında tüm dizisi oluşturur Bu durumda, her karşılık vermektedir.

karma (belleğe mevcut kıyasla) çok büyük olduğunda Yani, "her" gerçek faydası yoktur tek yerdir. Yani küçük bellek ile bir el veri toplama cihazı falan programlama sürece karma kendisi bizzat bellekte yaşamayan yaşanma sadece olasıdır.

Bellek sorunu değilse, genellikle harita veya tuşları paradigma paradigma okumak için daha prevelant ve kolaydır.

Cevap 11/09/2008 saat 23:04
kaynak kullanıcı

oy
5

Bu konuyla ilgili bir kaç muhtelif düşünceler:

  1. Karma Yineleyicilerin kendileri herhangi biri hakkında güvensiz bir şey yoktur. Ne güvensiz bunun üstesinden yineleme yaparken karmasının bir anahtarlarını değiştirerek olduğunu. (Bu değerleri değiştirmek için tamamen güvenli.) Olduğunda düşünebildiğim tek potansiyel yan etki valuesbunları değiştirerek karma içeriğini değiştirir yani takma adları döndürür. Bu tasarım gereğidir ancak bazı durumlarda istediklerini olmayabilir.
  2. John'un kabul cevabı bir istisna dışında iyidir: dokümantasyon bir karma yineleme sırasında anahtarları eklemek güvenli değildir açıktır. Bazı veri kümeleri için çalışabilir ancak karma sipariş bağlı diğerleri için başarısız olur.
  3. Zaten belirtildiği gibi, tarafından döndürülen son anahtarını silmek güvenlidir each. Bu değil için geçerli keysolduğu gibi eachbir yineleyici varken keysgetiri listesi.
Cevap 15/09/2008 saat 22:36
kaynak kullanıcı

oy
4

Her zaman yöntem 2 de kullanılır. Sadece, sürekli de-başvuran değiliz karma (daha doğrusu yeniden görevlendirilmesi yerine) karma girdisinin değerini okuyorsanız her kullanmanın tek avantajıdır.

Cevap 06/08/2008 saat 05:04
kaynak kullanıcı

oy
4

Bu sefer tarafından ısırıldı olabilir ama kişisel tercih olduğunu düşünüyorum. Ben cevabı "diye farklı dönüş" bariz dışındaki tuşları () veya değerler () (farklı olmak üzere) her (hiç docs herhangi bir başvuru bulamıyor. Aslında dokümanlar kullanacağım aynı yineleyici devlet ve hepsi yerine onları kopya gerçek liste değerlerini döndürmek ve herhangi bir çağrı kullanarak üzerinde yineleme sırasında karma değiştirerek o kötü.

Bütün bunlar, neredeyse her zaman karma kendisi aracılığıyla anahtarın değerini erişmek için genellikle daha kendini belgeleyen çünkü bana tuşlarını () kullanın. Zaman zaman değer anahtarı gereksiz, bu noktada önceden yapısında depolanan edilmiş büyük bir yapı ve karma anahtar için bir referans olan değerler () kullanmak ve bunu gerek yoktur. ) Ben Perl programlama 10 yıl içinde her () 2 kez kullandım düşünüyorum ve muhtemelen her iki kere = yanlış seçimdi

Cevap 06/08/2008 saat 04:43
kaynak kullanıcı

oy
1

Ben genellikle kullanmak keysve ben kullanılan son kez düşünmek veya bir kullanımını okuyamaz each.

Unutmayın mapEğer döngü içinde ne yaptığınızı bağlı!

map { print "$_ => $hash{$_}\n" } keys %hash;
Cevap 22/08/2008 saat 16:31
kaynak kullanıcı

oy
-2

Diyorum woudl:

  1. en kolay, onu kullanın (şimdiye anahtarlar, genellikle, ben iddia ediyorum) çoğu insan için anlaşılması / okuma
  2. Eğer bütün kod tabanı düşünce tutarlı karar ne olursa olsun kullanımı.

Bu 2 büyük avantajlar elde:

  1. Bu yeniden faktörünü böylece işlevleri / Bir yarıyılda içine "ortak" kod noktaya kolay.
  2. Gelecekteki geliştiriciler korumak için daha kolay olur.

Ben her aşkın tuşlarını kullanmak daha pahalı olduğunu düşünüyorum, bu yüzden kodunuzda aynı şey için iki farklı yapılara gerek yoktur.

Cevap 20/12/2010 saat 13:46
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more