Rubyでオブジェクトを要素とする配列をソートする際の覚え。

設定

 例えば、1クラス(例10人)の名前と身長と体重をオブジェクトにしてそれを配列として

  • 名前でソート
  • 身長でソート
  • 体重でソート

したいという状況を考えます。

データ構造をStructでつくり、これを配列に追加していきます。

Item = Struct.new(:name, :height, :weight)

a = []

a << Item.new("aa",155,45)
a << Item.new("bb",170,50)
a << Item.new("cc",175,57)
a << Item.new("dd",160,52)
a << Item.new("ee",165,49)
a << Item.new("ff",140,40)
a << Item.new("gg",185,75)
a << Item.new("hh",140,50)
a << Item.new("ii",175,65)
a << Item.new("jj",180,70)

配列の比較の定義

  • name
  • height
  • weight

でソートするには以下のようにします。

b = a.sort{|aa, bb|
      aa.name <=> bb.name
    }
    
c = a.sort{|aa, bb|
      aa.height <=> bb.height
    }
 
d = a.sort{|aa, bb|
      aa.weight <=> bb.weight
    }

e = a.sort{|aa, bb|
      bb.name <=> aa.name
    }

最後のeは、名前の逆順ソートになります。

結果

結果を表示するためには

print "sort by name\n"
    
 b.each {|aa|
    print aa.name,"\t",aa.height,"\t", aa.weight,"\n"
 }
 print "\nsort by height\n"

 c.each {|aa|
    print aa.name,"\t",aa.height,"\t", aa.weight,"\n"
 }
 print "\nsort by weight\n"

 d.each {|aa|
    print aa.name,"\t",aa.height,"\t", aa.weight,"\n"
 }
 print "\nsort by name reversely\n"
 e.each {|aa|
    print aa.name,"\t",aa.height,"\t", aa.weight,"\n"
 }
sort by name
aa	155	45
bb	170	50
cc	175	57
dd	160	52
ee	165	49
ff	140	40
gg	185	75
hh	140	50
ii	175	65
jj	180	70

sort by height
ff	140	40
hh	140	50
aa	155	45
dd	160	52
ee	165	49
bb	170	50
ii	175	65
cc	175	57
jj	180	70
gg	185	75

sort by weight
ff	140	40
aa	155	45
ee	165	49
hh	140	50
bb	170	50
dd	160	52
cc	175	57
ii	175	65
jj	180	70
gg	185	75

sort by name reversely
jj	180	70
ii	175	65
hh	140	50
gg	185	75
ff	140	40
ee	165	49
dd	160	52
cc	175	57
bb	170	50
aa	155	45

感想

1次元配列のソートは良くやりますが、オブジェクトを要素としてそのインスタンス変数をソートのキーにしてオブジェクトをそのまま並び替えできるのは、かなり楽だと思う。逆順にするのも、sortのところで比較の並べ方を変えてできてしまう。

イテレーター、オブジェクトを配列にして要素を呼び出す際のやり方は、Cでコーディングするような発想になっているかと思います。もっとシンプルにやれるかも。オブジェクトを使いこなしているとはいえないのですが、rubyすげーって感じなので備忘のために残しておくことにしました。