LoginSignup
29
35

More than 5 years have passed since last update.

Rubyで2次元配列のソートいろいろ

Last updated at Posted at 2016-09-18

はじめに

Rubyの勉強してて、2次元配列のソートでつまずいたので、その時、調べた備忘録です。

さっそく本題

例)arr = [[1, 3], [1, 5], [1, 2], [2, 4], [2, 2]] をソートしたい

① arr[1]で昇順にソート

sort()
p arr.sort {|a,b| a[1] <=> b[1]}
# 値が数値、文字に関わらず有効
sort_by()
p arr.sort_by {|x| x[1]}
# 値が数値、文字に関わらず有効

② arr[1]で降順にソート

sort()
p arr.sort {|a,b| a[1] <=> b[1]}.reverse
# 昇順.reverse
# 値が数値、文字に関わらず有効

または

p arr.sort {|a,b| b[1] <=> a[1]}
# b<=>a
# 値が数値、文字に関わらず有効
sort_by()
p arr.sort_by {|x| x[1]}.reverse
# 昇順.reverse
# 値が数値、文字に関わらず有効

または

p arr.sort_by {|x| -x[1]}
# -x
# 値が数値のみ有効

③ arr[0]で昇順 -> arr[1]で昇順にソート

sort()
p arr.sort {|a, b| (a[0] <=> b[0]).nonzero? || (a[1] <=> b[1])}
# (第1キー).nonzero? || (第2キー)
# 値が数値、文字に関わらず有効
sort_by()
p arr.sort_by {|x| [x[0], x[1]]}
# [第1キー, 第2キー]
# 値が数値、文字に関わらず有効

④ arr[0]で昇順 -> arr[1]で降順にソート

sort()
p arr.sort {|a, b| (a[0] <=> b[0]).nonzero? || (b[1] <=> a[1])}
# 値が数値、文字に関わらず有効
sort_by()
p arr.sort_by {|x| [x[0], -x[1]]}
# 値が数値のみ有効

最後に

④のケースで文字配列に対して、sort_byを使用した方法が、どうしてもわかりませんでした。
そもそも出来るのかもわかりませんが、もしわかる方がいましたら、教えていただけると助かります。

追記

④のケースで、1つ考えてみました。
たぶん、期待通り動作すると思います。
注)この実装では、ソートが安定しません。

sort_by()
p arr.sort_by {|x| x[1]}.reverse.sort_by {|x| x[0]}
# sort_by(第2キー).reverse.sort_by(第1キー)
# 値が数値、文字に関わらず有効

一応、ベンチマークを取ってみたところ、sort()を使用したケースより、速かったです。

追記2

「追記」の実装、@HMMNRST さんよりご指摘をいただきました。
こちらの実装なら大丈夫そうです。

sort_by()
i = 0
p arr.sort_by {|x| [x[1], i += 1]}.reverse.sort_by {|x| [x[0], i += 1]}
# sort_by(第2キー).reverse.sort_by(第1キー)
# 値が数値、文字に関わらず有効
29
35
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
35