知人のRubyコードを勝手に添削してみました

ライブドアブログ(livedoor Blog)| 読みたいブログが見つかる
勝手に添削をさらに勝手に書き直す - takkan_mのNo planな日常
僕も添削してみました。縛りは他の方と同じで「プログラムの構造など、劇的な変化はしない。例: クラスやメソッド構造など」です。以下、id:takkan_mさんのをベースに変更しています。

#!/usr/bin/env ruby

require 'pp'
require 'enumerator'

#def functions

def make_cluster(centroid, num_array)
  num_array.partition {|v| (centroid[0] - v) ** 2 < (centroid[1] - v) ** 2 }
end

def make_centroid(cluster)
  cluster.map do | c |
     c.empty? ? 0 : c.inject {|r, v| r + v } / c.size
  end
end

def calc_var(centroid, cluster)
  cluster.enum_for(:each_with_index).map do |clu, i|
    clu.inject(0.0) {|r, v| r + (v - centroid[i]) ** 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
   puts if counter != 0

   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
end

変更内容はこんな感じです。

  • num_array.selectのところは、Enumerable#partitionを使って書けました。
  • c.size == 0は、Array#empty?に変更しました。
  • cluster.zipはHaskellでは定石なのですが、Rubyではいまひとつ自信がありません。ここではenumeratorモジュールのObject#enum_forを使ってみました。
  • 改行を表示するputsを前に持ってきて、最初の一回は除外するようにしました(前のプログラムとの互換性のため)。あとただ改行するだけなので、引数の"\n"は省略しました。
  • puts 'centroid:'など、バックスラッシュ記法や変数展開のない文字列はシングルクォートで囲むようにしました。