2010-06-29 15 views
9

sağlamalarının Dizi Referans Sınıflandırma: Perl şu satırları çalıştırıldıktan sonra

my $data = `curl '$url'`; 
my $pets = XMLin($data)->(pets); 

I karma başvurular içeren bir dizi referans vardır: Perl

$VAR1 = [ 
     { 
     'title' => 'cat', 
     'count' => '210' 
     }, 
     { 
     'title' => 'dog', 
     'count' => '210' 
     } 
] 

, bir karma nasıl sıralarım İlk sayım ve ikincil olarak başlık. Daha sonra her yeni satırın başlığını takip eden sayımı STDOUT'a yazdırın.

cevap

9

Eğer artan azalan düzende sayıları ve unvanları istiyorum varsayarsak: kompakt kod fonksiyonel bir tarzda yazıldığı

print map join(" ", @$_{qw/ count title /}) . "\n", 
     sort { $b->{count} <=> $a->{count} 
         || 
      $a->{title} cmp $b->{title} } 
     @$pets; 

. Bunu anlamaya yardımcı olmak için, daha tanıdık ve zorunlu bir tarzda eşdeğer kodlara bakalım.

Perl's sort operatörü, karşılaştırmanızı dikkate almanıza ve ne yaptığını açıklayan bir ad vermenize izin veren isteğe bağlı bir SUBNAME parametresi alır. Bunu yaptığımda, by_ ile alt adını yazmaya başlamak için sort by_...'u daha doğal olarak hazırlamayı seviyorum.

hiçbir virgül bu formda SUBNAME izler

sub by_count_then_title { 
    $b->{count} <=> $a->{count} 
       || 
    $a->{title} cmp $b->{title} 
} 

my @sorted = sort by_count_then_title @$pets; 

Not yazmış olabilirim, başlamak için!

Başka bir yorumcının sorusunu ele almak için, daha okunaklı olduğunu fark ederseniz, by_count_then_title numaralı telefondan || yerine or kullanabilirsiniz. || ve or'dan çok <=> ve cmphave higher precedence (daha sıkı bir şekilde bağlayıcı olarak düşünebilirsiniz), bu kesinlikle bir stil meselesidir. Bir daha tanıdık bir seçim

foreach my $p (@sorted) { 
    print "$p->{count} $p->{title}\n"; 
} 

Perl olabilir

Her değerini alır değişkeni belirtmek yoksa $_ kullanan sıralı dizi yazdırmak için, bu yüzden aşağıdaki aynı anlama sahiptir:

for

for (@sorted) { 
    print "$_->{count} $_->{title}\n"; 
} 
ve foreach anahtar eş vardır, ama yukarıdaki kullanımları yani, foreach Ben bir var isim gidiyorsam bulmak iable veya for aksi takdirde, en doğal olarak okuyun.

map print("$_->{count} $_->{title}\n"), @sorted; 

Ayrıca map aracılığıyla print teşvik edebilir: yerine çok farklı değil, map, foreach yakın bir kuzeni kullanma

Son olarak

print map "$_->{count} $_->{title}\n", 
     @sorted; 

, $_->{...} tekrarını önlemek için hash slice@$_{"count", "title"} bize döngüdeki geçerli kayıtta sayım ve başlık ile ilişkili değerleri verir.değerlere sahip, biz tek bir boşluk ile join ve sonuca bir yeni satır eklemek gerekir, bu nedenle

print map join(" ", @$_{qw/ count title /}) . "\n", 
     @sorted; 

qw// dizeleri listesini yazmak için steno olduğunu unutmayın. Bu örnekte gösterildiği gibi, bir map ifadesini önden arkaya (veya girintilemenin altından üste doğru) okuyun: önce kayıtları sıralayın, sonra biçimlendirin, sonra yazdırın.

Sen adında bir karşılaştırma geçici @sorted ortadan kaldırmak ancak diyebiliriz: join uygulanması sonra, zevkinize için çok ayrıntılı ise

print map join(" ", @$_{qw/ count title /}) . "\n", 
     sort by_count_then_title 
     @$pets; 

demek "map" neyi

print map "@$_{qw/ count title /}\n", 
     sort by_count_then_title 
     @$pets; 
+0

/Yukarıdaki kodda yapmak? Ve neden iki niteliği iki farklı küme parantez içinde belirtmemiz gerekmedi? – syker

+0

@syker: 'map', sıralanmış dizinizdeki her hashı alır ve' count' ve 'title' değerlerini boşlukla ayrılmış bir satıra yazdırır. @gbacon: Sıralamasında her zaman gördüğüm gibi '||' ile '' '' '' 'arasında bir fark olup olmadığını açıklamaya değebilir. Daha okunaklı olan 'ya da' herhangi bir koşulda farklı davranma olasılığı var mıdır? – Zaid

+0

@syker @Zaid Güncellenmiş yanıtlara bakın. –

İlgili konular