_  _   ,_
/^\/^\-/ @D
~(________/ PERL.LT
|L |L
L L
Straipsniai  Funkcijos 
Funkcijos/sort - perrikiuoti reikšmių sąrašą

  • sort SUBNAME LIST
  • sort BLOCK LIST
  • sort LIST

    Sarašo kontekste, komanda išrūšiuoja LIST ir gražina išrūšiuoto sarašo reikšmę, Skaliariniame kontekste, sort() elgesys neapibrėžtas.

    Jei SUBNAME ar BLOCK praleisti, sortišrūšiuoja standartine palyginimo tvarka. Jei SUBNAME apibrėžtas, jis nusako paprogramio pavadinimą, kuris gražina sveikąjį skaičių mažiau nei, lygų arba didesnį nei 0 , priklausomai nuo to, kaip elementus sąraše pageidaujama sutvarkyti. (<=> ir cmp komandos yra ypatingai pravarčios tokiose situacijose.) SUBNAME gali būti skaliarinis kintamojo vardas (be parašo), kuriuo atveju reikšmė suteikia pavadinimą (ar linką į) naudotiną paprogramę. Vietoj SUBNAME, galima suteikti BLOCK anoniminę, vienoje eilutėje veikiančios paprogramės prasmę.

    Jei paprogramės prototipas yra ($$) , elementai, kuriuos norima palyginti yra perduodami pagal nuorodą @_ , kaip paprastai paprogramei. Taip yra lėčiau nei neprototipinėms paprogramėms, kur elementai, kuriuos norima palyginti yra perduodami paprogramei kaip globalių kintamųjų $a ir $b rinkinys (pavyzdys žemiau). Pažymėtina, jog pastaruoju atveju, dažniausia neproduktyvu deklaruoti $a ir $b kaip žodinius kintamuosus (lexical).

    Abiem atvejais, paprogramės negali būti rekursinės. Reikšmės, kurias norima palyginti visada perduodamos per reference'us, taigi jų modifikuoti nereikia.

    Taip pat galima išeiti iš sort bloko ar paprogramės, naudojant kuriuos nors ciklų operatorius, aprašytusperlsyn ar su goto.

    Kai use locale naudojamas, sort LIST išrūšiuoja LIST priklausomai nuo esamos lokalizacijos. Skaityti perllocale.

    Perl 5.6 ir ankstesni naudojo quicksort algoritmą realizuoti išrūšiavimą. (Tas algoritmas nebuvo stabilus ir galėjo pavirsti kvadratine lygtimi. stabilus rūšiavimas saugo įvedimo tvarką tų elementų, kuriuos mano esant lygiais. Nors quicksort'o skaičiavimo laikas yra O(NlogN), kuomet suvidurkintas visų N ilgio masyvų, jis gali padidėti iki O(N**2), kvadratiškumo elgsena kai kuriems įvedimams.) 5.7, quicksort realizacija buvo pakeista į stabilų mergesort algoritmą, kurio blogiausiu atveju skaičiavimo laikas būdavo O(NlogN). Bet sistemų darbo bandymai parodė, kad kai kuriais atvejais, atskirose platformose, originalus quicksort buvo greitesnis. 5.8 turi sort pragmą ribojamai rūšiavimo kontrolei. Tai ganėtinai nenuovoki esančio algoritmo kontrolė, kuri gali nebesitęsti ateities versijose, tačiau galimybė charakterizuoti įvestį ir išvestį greičiausiai tęsis. Skaityti sort.

    Pavyzdžiai:

        # rūšiuoti pagal žodyną
        @articles = sort @files;
        # tas pats, bet su tiksliu rūšiavimo    
        @articles = sort {$a cmp $b} @files;
        # dabar nepaisant didžiųjų ir mažųjų raidžių
        @articles = sort {uc($a) cmp uc($b)} @files;
        # tas pats tik atvirkščia tvarka
        @articles = sort {$b cmp $a} @files;
        # išrūšiuoti pagal skaičių didėjančia tvarka
        @articles = sort {$a <=> $b} @files;
        # išrūšiuoti pagal skaičių mažėjančia tvarka
        @articles = sort {$b <=> $a} @files;
        # išrūšiuoja %age hash pagal vertę vietoj rakto 
        # naudodamas in-line funkciją
        @eldest = sort { $age{$b} <=> $age{$a} } keys %age;
        # išrūšiuoti naudojant tikslų paprogramės vardą
        sub byage {
    	$age{$a} <=> $age{$b};	# presuming numeric
        }
        @sortedclass = sort byage @class;
        sub backwards { $b cmp $a }
        @harry  = qw(dog cat x Cain Abel);
        @george = qw(gone chased yz Punished Axed);
        print sort @harry;
    	    # išveda AbelCaincatdogx
        print sort backwards @harry;
    	    # išveda xdogcatCainAbel
        print sort @george, 'to', @harry;
    	    # išveda AbelAxedCainPunishedcatchaseddoggonetoxyz
        # neefektyvius išrūšiavimas pagal mažėjančių numerių palyginimą naudojant
        # pirmąjį sveiką skaičių po pirmojo = ženklo arba
        # visą įrašą nepaisant didžiųjų ir mažųjų raidžių
        @new = sort {
    	($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0]
    			    ||
    	            uc($a)  cmp  uc($b)
        } @old;
        # tas pats, bet daug efektyviau;
        # greitumo labui įsivedami papildomi indeksai
        @nums = @caps = ();
        for (@old) {
    	push @nums, /=(\d+)/;
    	push @caps, uc($_);
        }
        @new = @old[ sort {
    			$nums[$b] <=> $nums[$a]
    				 ||
    			$caps[$a] cmp $caps[$b]
    		       } 0..$#old
    	       ];
        # tas pats, bet be laikinų kintamųjų
        @new = map { $_->[0] }
               sort { $b->[1] <=> $a->[1]
                               ||
                      $a->[2] cmp $b->[2]
               } map { [$_, /=(\d+)/, uc($_)] } @old;
        # naudojant prototipą, leidžia panaudoti palyginimo paprogramę
        # kaip rūšiavimo paprogramę (įskaitant kitas rinkinio paprogrames)
        package other;
        sub backwards ($$) { $_[1] cmp $_[0]; }	# $a ir $b nenustatomi čia
        package main;
        @new = sort other::backwards @old;
        # garantuoja stabilumą, nepaisant algoritmo
        use sort 'stable';
        @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old;
        # priverstinai naudojamas mergesort (neportabilus, jei ne Perl 5.8)
        use sort '_mergesort';  # Pastebėkime "_"
        @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old;

    Jeigu naudojamas strict negalima deklaruoti $a ir $b kaip žodyninių (lexicals). Jie yra globalūs tame rinkiny (package). Tai yr, jei esama pagrindiniame rinkinyje ir surinkus

        @articles = sort {$b <=> $a} @files;

    tada $a ir $b yra $main::a ir $main::b (arba $::a ir $::b ), bet jei esamaFooPack package, tai tas pats kas surinkus

        @articles = sort {$FooPack::b <=> $FooPack::a} @files;

    Palyginimo funkcija turi kažką daryti. Jei ji gražina prieštaringus rezultatus (kartais $x[1] mažesnis nei $x[2], o kartais atvirkščiai, pavyzdžiui) rezultatai nėra tiksliai nusakyti.

    Todėl, kad <=> gražina undef kai abu operandai yra NaN (not-a-number, ne skaičiai) ir todėl, kad sort mes fatal error kol palyginimo rezultatas bus apibrėžtas. Rūšiuojant su palyginimo funkcijomis kaip $a <=> $b , reikia saugotis sąrašų, kurie gali turėti NaN . Kitas pavyzdys tuo ir pasinaudoja, kad NaN != NaN išeliminuodamas visus NaN iš įvesties.

        @result = sort { $a <=> $b } grep { $_ == $_ } @input;
algirdas@perl.lt 2005.04.11 - $dabar