2009-11-30 3 views
50

Perl'deki hashları doğru olarak anlamak istiyorum. Perl'i bir süreliğine aralıklı olarak kullanmam gerekti ve çoğunlukla ne zaman yapmam gerekiyorsa, çoğunlukla metin işlemeyle ilgili.Perl'de karma ve karma referans arasındaki fark nedir?

Ve her seferinde, karmalarla uğraşmak zorundayım, o da berbat. Bu yazım hataları ve karma referansları hakkında iyi bir açıklama, ihtiyaç duydukları zaman, vb. Için çok şifreli olan çok fazla takdir edilecektir.

+35

_ * size bir elmayı uzatır * _ bir karma olduğunu farz et. _ * eller el buzdolabında bir elmaya yol tarifi yazdı * _ bu bir karma referanstır. –

+2

_hearning Perl_'un karma bölümleri konusundaki bölümüne bakabilirsiniz. –

+0

@ ~ quack: Keşke bir yorum yapmaktan ziyade bir cevap olmuş olsaydım, böylece seni doğru şekilde söyleyebilirim. –

cevap

78

Basit bir karma bir diziye yakın. Başlatmaları bile benzer gözüküyor.İlk dizi:

@last_name = (
    "Ward", "Cleaver", 
    "Fred", "Flintstone", 
    "Archie", "Bunker" 
); 
Şimdi

en karmasının (aka ilişkisel dizi) ile aynı bilgiyi temsil edelim: aynı ada sahip olsa da

%last_name = (
    "Ward", "Cleaver", 
    "Fred", "Flintstone", 
    "Archie", "Bunker" 
); 

, dizi @last_name ve karma %last_name tamamen bağımsızdır . Biz Archie soyadını bilmek istiyorsak, doğrusal bir arama gerçekleştirmek zorunda dizi ile

: karma ile

my $lname; 
for (my $i = 0; $i < @last_name; $i += 2) { 
    $lname = $last_name[$i+1] if $last_name[$i] eq "Archie"; 
} 
print "Archie $lname\n"; 

, çok daha direkt sözdizimsel var:

print "Archie $last_name{Archie}\n"; 

Say Sadece biraz daha zengin yapısı ile bilgiyi göstermek istiyoruz:

  • Cleaver (soyad)
    • Ward (ad)
    • Haziran (eşinin ilk ad)
      • Fred
      • Wilma
    • Bunker
    • Çakmaktaş referanslar gelmeden önceArchie
    • Edith

, düz anahtar-değer karmaları biz gelen en iyisi, ama referanslar, Dahili olarak anahtarları ve değerleri

my %personal_info = (
    "Cleaver", { 
     "FIRST", "Ward", 
     "SPOUSE", "June", 
    }, 
    "Flintstone", { 
     "FIRST", "Fred", 
     "SPOUSE", "Wilma", 
    }, 
    "Bunker", { 
     "FIRST", "Archie", 
     "SPOUSE", "Edith", 
    }, 
); 

izin %personal_info, skalerlerin tümüdür, ancak değerler, özel bir tür skaler: hash başvurusu olup, {} ile oluşturulmuştur. Referanslar "çok boyutlu" karmaları simüle etmemize izin veriyor. Örneğin, Perl bize simgeler arasındaki okları çıkarmanıza olanak sağlar

$personal_info{Flintstone}->{SPOUSE} 

Not yoluyla Wilma alabilirsiniz, bu nedenle yukarıdaki bilmeni istiyorum eğer yazarak bir sürü

$personal_info{Flintstone}{SPOUSE} 

eşdeğerdir daha Fred, böylece bir imleç tür olarak bir başvuru kapmak olabilir:

$fred = $personal_info{Flintstone}; 
print "Fred's wife is $fred->{SPOUSE}\n"; 

yukarıdaki kod parçasında $fred bir hashref olduğundan, ok gereklidir.

Global symbol "%fred" requires explicit package name at ... 

Perl referansları C ve C++ işaretçiler benzer, ancak bunlar boş olamaz: Eğer dışarı bırakır ama akıllıca hataların bu tür yakalamak için use strict etkinse, derleyici şikayet edecektir. C ve C++ öğelerindeki işaretçiler, dizgeyi gerektirir ve bu nedenle Perl'de başvurular yapılır.

C ve C++ işlev parametrelerinin değer-arası anlamsallıkları vardır: bunlar yalnızca kopyalardır, bu nedenle değişiklikler arayana geri dönmez. Değişiklikleri görmek isterseniz, bir işaretçiyi geçmelisiniz. Sen Perl referanslarla bu etkiyi elde edebilirsiniz:

sub add_barney { 
    my($personal_info) = @_; 

    $personal_info->{Rubble} = { 
     FIRST => "Barney", 
     SPOUSE => "Betty", 
    }; 
} 

add_barney \%personal_info; 

ters eğik çizgi olmadan, add_barney alt döndüğü anda atılır oluyor bir kopyasını kazanılmış olacaktı.

Ayrıca, yukarıdaki "yağ virgül" (=>) 'un kullanımını da unutmayın. Soldaki dizeyi otomatik olarak seçer ve karma başlatmaları daha az sözdizimsel olarak gürültülü hale getirir.

+0

C ve C++ bir işaretçiyi kullanmadan başvuruya izin verdiğine dikkat çekmek için 7 yıl sonra bırakıyor. void f (DataType & arg) '' arg 'öğesini referans olarak geçirir ve erişim veya değişiklik yapmak için kaynak kodlama gerektirmez. –

+0

@JimV Bu, bir takma ad olan "&" ile bildirilen bir _reference_ ilettiğinizde. Semantik _is_-değer-değer. – zdim

+0

Harika bir yazı :). Bir yorum - belki de bir uyarı notu, '_' argümanlarını taklit eder, yani bir _can_ onları alttan değiştirir (hash tuşları hariç)? – zdim

10

A hash, Perl'de temel bir veri türüdür. İçeriğine erişmek için tuşlarını kullanır.

Bir hash ref, bir hash için referansının kısaltmasıdır. Referanslar skaler olup, basit değerlerdir. , esas olarak karma değerinin kendisine bir işaretçi olan içeren bir skaler değerdir.

Bağlantı: difference between hash and hash ref in perl - Ubuntu Forums

bir fark silme sözdizimi içerisindedir. C gibi, Perl karma için bu gibi çalışır:

delete $hash{$key}; 

ve Hash Kaynaklar

delete $hash_ref->{$key}; 

Perl Hash Howto da başka yoktur

Hash Referanslarla Hash karşı karmaları anlamak için mükemmel bir kaynaktır

bağlantı here that has more information on perl and references.

6

Kendi bilgisayarınızın komut satırında da bulunan perldoc perlreftut adresine bakın.

Başvuru, tüm diziye veya tüm kareye (veya hemen hemen her şeye) karşılık gelen skaler bir değerdir. İsimler zaten aşina olduğunuz bir tür referanstır. Amerika Birleşik Devletleri Başkanı düşünün: dağınık, rahatsız edici bir kan ve kemik torbası. Ama onun hakkında konuşmak ya da onu bir bilgisayar programında temsil etmek için tek ihtiyacınız olan kolay, kullanışlı skaler dizge "Barack Obama".

Perl'deki kaynaklar diziler ve karma isimleri gibidir. Onlar Perl'in özel iç isimleri, bu yüzden kesin olduklarından emin olabilirsiniz. "Barack Obama" dan farklı olarak, bir referans sadece bir şeye atıfta bulunur ve her zaman ne ifade ettiğini bilirsiniz. Bir diziye referansınız varsa, dizinin tamamını buradan kurtarabilirsiniz. Bir hash referansı varsa, tüm hash elde edebilirsiniz. Ancak referans, hala kolay, kompakt bir skaler değerdir.

my %hash = (
    toy => 'aeroplane', 
    colour => 'blue', 
); 
print "I have an ", $hash{toy}, " which is coloured ", $hash{colour}, "\n"; 

my $hashref = \%hash; 
print "I have an ", $hashref->{toy}, " which is coloured ", $hashref->{colour}, "\n"; 

Ayrıca perldoc perldsc bkz:

+0

@ mjp66 Cevabın asıl kısmı, OP'nin bilgisayarında 'perl' yanında yüklü olan perldoc perlreftut 'kullanmaktır. OP'nin kullandığı perl * 'in * özel sürümü için her zaman en doğru belge budur. Bağlantı sadece nezaket olarak dahil edilmiştir. Yani, bu anlamda, Perl dokümantasyon URL'leri sadece referanslar gibidir. Bağlantıdaki içerik değişebilir, ancak bağlantı her zaman "Perl References Tutorial" a işaret edecektir. Tüm bağlantılar eşit oluşturulmaz. Bilginize. –

15

şu bir karma ve karma başvuru kullanabilirsiniz nasıl kullanılacağını gösterir.

+8

Şahsen, bir karma tanımlamak için '% hash' terimini görmek için kafa karıştırıcı buldum. Evinizi sürmek için '% hash'ınızı'% favorite 'olarak yeniden etiketlemek iyi bir fikir olabilir. Baskı ifadesi daha sonra "baskı" gibi bir şey olurdu. En sevdiğim oyuncak $ favori {toy} "; – Zaid