test_STM.pl
# Schwartzian Transform Method # First Section --- Difinition of @LIST --- # Difinition of @LIST @LIST = ('1,21,4' , '5,33,43' , '15,2,5' , '12,15,21'); print "@LIST\n"; # Second Section --- Get Refference of each line in @LIST --- # For each elements in @LIST foreach (@LIST){ # Split now-specificated element in @LIST by ",". # In @tmp, there are 3 elements. These are values. my @tmp = split(/,/,$_); # Get @tmp's refference by "[ ]". # In @tmp, there are 3 elements. These are refferences. my @tmp = [@tmp]; # Add them to @tmp_LIST # In @tmp_LIST, 3 elements added each times. These are refferences. push @tmp_LIST,@tmp; } print "@tmp_LIST\n"; # Forrowing is the same working # map{} gets forrowing array and returns the result of the statement in { }. # @tmp_LIST = map{[split(/,/,$_)]} @LIST; # print "@tmp_LIST\n"; # Third Section --- Sort @LIST by using derefference of @tmp_LIST --- # $a and $b is refference of @LIST. # And derefference them by operator ->[]. So $a->[2] and $b->[2] are values themselves. # Sort them by values. Rewrite @tmp_LIST. # Sort gets a forrowing array and returns a value of the array by criterion in {}. # In @tmp_LIST, there are 4 elements. These are refferences. #@tmp_LIST = sort{$a->[2] cmp $b->[2]} @tmp_LIST; # If sorting them by number is needed, forrowing is sutable. @tmp_LIST = sort{$a->[2] <=> $b->[2]} @tmp_LIST; print "@tmp_LIST\n"; # Fourth Section --- Join them --- # For each elements in @tmp_LIST foreach(@tmp_LIST){ # Get values themselves refferenced by $_. my @tmp = @$_; # Join each elements in @tmp by ",". my @tmp = join(',',@tmp); # Add them to @NEW_LIST. push @NEW_LIST,@tmp; } print "@NEW_LIST\n"; # Forrowing is the same working #@NEW_LIST = map{join',',@$_} @tmp_LIST; #print "@NEW_LIST\n"; # All sections can be written in one line. # Forrowing is One line style about upper sections. #@NEW_LIST = map{join',',@$_} sort{$a->[2] cmp $b->[2]} map{[split',']} @LIST; #@NEW_LIST = map{join',',@$_} sort{$a->[2] <=> $b->[2]} map{[split',']} @LIST; #print "@NEW_LIST\n";
例えば下のようにするとa.dat中の1カラムにxの値、2カラムに二次関数の値がセットされるんだな。
C:\>perl -le "sub f{($a,$b,$c)=(rand,rand,rand);return $a*$_**2+$b*$_+$c;} for(-9..9){$x=$_+rand;$f=&f($x);print \"$x $f\";}">a.dat C:\>
結果を表示すると下のようになるんだな。
C:\>perl -le "@a=<>; print @a;" a.dat -8.77401733398438 72.4348754882813 -7.83602905273438 5.97018432617188 -6.059326171875 35.9939270019531 -5.44882202148438 33.2612609863281 -4.21817016601563 9.92474365234375 -3.3221435546875 -1.31829833984375 -2.09671020507813 3.02935791015625 -1.600341796875 2.762939453125 -0.749908447265625 0.922332763671875 0.154327392578125 0.6827392578125 1.42169189453125 2.23629760742188 2.8875732421875 2.50311279296875 3.66021728515625 7.56057739257813 4.10379028320313 19.9759826660156 5.96383666992188 5.775146484375 6.0418701171875 17.5700378417969 7.32489013671875 35.4329223632813 8.97604370117188 31.3730163574219 9.09332275390625 29.8526916503906 C:\>
これを上の方法を使って2カラム目でソートしてみるんだな。
C:\>perl -le "@a=<>; @b=map{join' ',@$_}sort{$a->[1]<=>$b->[1]}map{[split/\s/]}@a; for(@b){print}" a.dat -3.3221435546875 -1.31829833984375 0.154327392578125 0.6827392578125 -0.749908447265625 0.922332763671875 1.42169189453125 2.23629760742188 2.8875732421875 2.50311279296875 -1.600341796875 2.762939453125 -2.09671020507813 3.02935791015625 5.96383666992188 5.775146484375 -7.83602905273438 5.97018432617188 3.66021728515625 7.56057739257813 -4.21817016601563 9.92474365234375 6.0418701171875 17.5700378417969 4.10379028320313 19.9759826660156 9.09332275390625 29.8526916503906 8.97604370117188 31.3730163574219 -5.44882202148438 33.2612609863281 7.32489013671875 35.4329223632813 -6.059326171875 35.9939270019531 -8.77401733398438 72.4348754882813 C:\>
たったこれだけでソートできてしまうんだな。キモはmap{}を使うとこなんだな。これを使うとforeach{}文で配列にpushするような場合のスクリプトを短く書けるんだな。