多重配列の複数オーダーソート

ついでなんで。
Generator なんて初めて使いまった。Generator っていうより Iterator だよね。

#!/usr/bin/ruby
require 'generator'

class Symbol
   def <=> b
      self.to_s <=> b.to_s
   end
end

def rcmp(a, b, i)
   c = i.current
   if a[c] == b[c] && i.next?
      i.next
      return rcmp(a, b, i)
   else
      i.rewind
      return a[c] <=> b[c]
   end
end

class Array
   def order_by(*order)
      return nil unless order

      if order.size == 1
         return self.sort_by{|e| e[order[0]]}
      else
         i = Generator.new(order)
         return self.sort { |a,b| rcmp(a, b, i) }
      end
   end
end

m_ary = [
   ["a", 5],
   ["b", 4],
   ["a", 3],
   ["c", 2],
   ["a", 1],
]


if __FILE__ == $0
   puts "ORDER BY 1:"
   m_ary.order_by(1).each do |e|
      puts "\t" + e.inspect
   end

   puts "ORDER BY 0,1:"
   m_ary.order_by(0, 1).each do |e|
      puts "\t" + e.inspect
   end

   puts "ORDER BY 0 but Symbol"
   m_ary.map{|e| [e[0].to_sym, e[1]]}.order_by(0).each do |e|
      puts "\t" + e.inspect
   end
end

わざわざ作らないでも Math にありそう、もしくは、ググれば落ちてそう。


LINQ っぽく Ruby で書く 時、順番を複数指定したい場合、カンマ区切り等で簡単に書けないよなと思って。けど、趣旨がずれてしまって、ブロック取らないし Struct や オブジェクトを要素とした配列にも対応してない。誰かやって。


あー、しまった、sort_by で配列を受け付けるように手を入れた方が良かったかぁ?