2012-01-13 13 views
13

Sıralamak istediğim bir dizi dizim var. A dizisinin her elemanı 3 öğeli bir dizidir. Ben artan düzende bir sıralamak istiyorumPerl dizisini sıralamak istiyorum, ancak sonuç sıralanmamış

my @A = ([2,3,1], [1,2,3], [1,0,2], [3,1,2], [2,2,4]); 

: gibi Dizi A görünüyor. 2 elemanı karşılaştırırken, ilk sayı kullanılır. Bir kravat varsa, ikinci sayı kullanılır ve daha sonra üçüncü sayı.

İşte kodum. 2 elemanı karşılaştırmak için 'cmpfunc' işlevini kullanıyorum.

sub cmpfunc { 
    return ($a->[0] <=> $b->[0]) or 
      ($a->[1] <=> $b->[1]) or 
      ($a->[2] <=> $b->[2]); 
} 
my @B = sort cmpfunc @A; 
print "Result:\n"; 
for my $element (@B) { 
    print join(",", @{$element}) . "\n"; 
} 

Sonuç:

1,2,3 
1,0,2 
2,3,1 
2,2,4 
3,1,2 

sonuç biraz sınıflandırılır ancak doğru değildir. Beklediğim şey:

1,0,2 
1,2,3 
2,2,4 
2,3,1 
3,1,2 

Karşılaştırma işlevimde herhangi bir hata var mı? Tuhaf olan şey, karşılaştırma kodunu blokta koyduğumda, sonuç doğru şekilde sıralanıyor. Bunu "veya" arasındaki maddelerden herhangi birine girmeden önce döner

return ($a->[0] <=> $b->[0]) 

yürütme

sub cmpfunc { 
    return (($a->[0] <=> $b->[0]) or 
      ($a->[1] <=> $b->[1]) or 
      ($a->[2] <=> $b->[2])); 
} 
+0

İlgili: http://stackoverflow.com/questions/1512547 – mob

cevap

21

:

my @C = sort { ($a->[0] <=> $b->[0]) or 
       ($a->[1] <=> $b->[1]) or 
       ($a->[2] <=> $b->[2]) } @A; 
+8

* VEYA * daha sıkı bağlama kullanın veya: '||'. – Axeman

5

daha parantez ihtiyacı var.

Ya "dönüş" anahtar kelime kaldırma veya geri dönüşü için tüm arg listeye etrafında parantez ekleyin:

sub cmpfunc { 
    return(($a->[0] <=> $b->[0]) or 
      ($a->[1] <=> $b->[1]) or 
      ($a->[2] <=> $b->[2])); 
} 
9

bu "yanlış" davranışı gözlemlemek nedeni or operatör, en düşük öncelikli olan mümkün. Saçma sapan bu durumda, dönüş döndürür asla - Bu durumda bu

return ($a->[0] <=> $b->[0]) or 
     ($a->[1] <=> $b->[1]) or 
     ($a->[2] <=> $b->[2]); 

olarak yorumlanır YA-ing

return ($a->[0] <=> $b->[0]) 

ve hattın kalanını demektir. :)

Yani C'nin OR kullanmalıdır:

return ($a->[0] <=> $b->[0]) || 
     ($a->[1] <=> $b->[1]) || 
     ($a->[2] <=> $b->[2]); 
+1

Teşekkürler, || iyi bir alternatif. – jftsai

3
sub cmpfunc { 
    return ($a->[0] <=> $b->[0]) or 
      ($a->[1] <=> $b->[1]) or 
      ($a->[2] <=> $b->[2]); 
} 

sen 'dönüşü' silebilirsiniz burada.

sub cmpfunc { 
    ($a->[0] <=> $b->[0]) or 
    ($a->[1] <=> $b->[1]) or 
    ($a->[2] <=> $b->[2]); 
} 
+0

Yine de doğru değerlendiren ilk ifadeyi döndürecek. –

+1

@LeonardoHerrera Bunu yapması gerekiyor. – TLP

+0

@TLP - doh, haklısın. –

2

Daniel'in bir alternatif çözüm:

sub cmpfunc { 
    return ($a->[0] <=> $b->[0]) || 
      ($a->[1] <=> $b->[1]) || 
      ($a->[2] <=> $b->[2]); 
} 

or bu durumda sorun o yüzden işlevi yalnızca -1 ($a->[0] <=> $b->[0]) sonucunu döndürür, atama daha düşük önceliğe sahip olmasıdır, 0 veya 1 ise, sol taraf sırasıyla, sağ tarafa eşit veya ondan daha büyükse.|| daha yüksek önceliğe sahiptir, bu nedenle, tüm boole ifadesi geri dönmeden önce değerlendirilir. Belirtildiği gibi, ||'a tercih ederseniz, ifadeyi parantez içine alabilirsiniz. Şahsen ben yok.

+0

Aslında, ne döndüğü önemli değil, yalnızca ilk karşılaştırmayı döndürür. Altında bir {return 0 veya die "Ough"} 'ı deneyin. – TLP

+0

@TLP: Bunu işaretlediğiniz için teşekkür ederiz. – flesk

İlgili konular