勝手に添削をさらに勝手に書き直す
rubyneko - 知人のRubyコードを勝手に添削してみたを見て、個人的に気になったところを勝手に直してみた。かなり、個人的な好みなので、これがいいのかわからないけど。
require 'pp' #def functions def make_cluster(centroid, num_array) c = num_array.select{|v| (centroid[0] - v)**2 < (centroid[1] - v)**2} [c,(num_array - c)] end def make_centroid(cluster) cluster.map do | c | c.size == 0 ? 0 : c.inject{|i,j| i + j}/c.size end end def calc_var(centroid, cluster) cluster.zip(centroid).map do | clu , cen | clu.inject(0.0){|i,j| i += (j - cen)**2} end end #end def functions num_array = [1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 6.0, 7.5, 8.0, 8.5, 9.0, 10.0] new_centroid = [0.0, 1.0] centroid = [0.0, 0.0] counter = 0 while centroid != new_centroid centroid = new_centroid cluster = make_cluster(centroid, num_array) puts "step#{counter}:" puts "centroid:" pp centroid #calc var puts "var:" pp calc_var(centroid, cluster) puts "cluster:" pp cluster new_centroid = make_centroid(cluster) counter += 1 puts "\n" end
まず、make_cluster関数は、別にもとのままでも良かったんだけど、勢いで書き直してみた。というか、if exp then a1 else a2 end << valという書き方ができるのを初めて知った。
make_centroid関数と、calc_var関数に関しては、先に結果の配列を作って、Rangeクラス使ってインデックスを作り、違う配列の同じインデックスの要素をつかって計算し、結果の配列のそのインデックスの位置に格納されていたんだけど、、それってzipしてmapでいいんじゃないかと。ここら辺は、haskellやりだしてから、自分の常套手段。
あと、最後の計算部分でloop使われていたんだけど、breakする条件があるのであれば、while使いたい。停止条件がうもれてしまうので。そのおかげで、元のソースより、出力される改行が一つ多くなってしまったんだけど。
ちなみに、ソースの長さはこんな感じになった。別に、ゴルフじゃないからいいんだけど。
: wc before.rb after.rb 65 147 1087 before.rb 49 123 893 after.rb