綾小路龍之介の素人思考

[ファイル編集] 表計算

Schwartzian Transform Methodについて書いてみようと思うんだな。まずは下のスクリプトを見てほしいんだな。

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するような場合のスクリプトを短く書けるんだな。

ソーシャルブックマーク

  1. はてなブックマーク
  2. Google Bookmarks
  3. del.icio.us

ChangeLog

  1. Posted: 2007-11-19T01:48:07+09:00
  2. Modified: 2007-11-19T04:45:14+09:00
  3. Generated: 2017-09-26T23:09:18+09:00