2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Scala] Seq[Option]において、NoneFirst、NoneLastのsortの実装について考えてみる

Last updated at Posted at 2019-05-08

要素がOption型のSeqについて、NoneFirst、NoneLastなソートがしたい場合があったので、いろいろ考えてみました。
(@yasube2613さんの助言を反映しました。コメントありがとうございました。)

今回考えるケース:

// サンプルデータ
// Seq(Some(1)), None, Some(3))

// 得たい結果
// Some(昇順) → Noneのソート
// Seq(Some(1), Some(3), None)

// Some(降順) → Noneのソート
// Seq(Some(3), Some(1), None)

// None → Some(昇順)のソート
// Seq(None, Some(1), Some(3))

// None → Some(降順)のソート
// Seq(None, Some(3), Some(1))

Orderingを定義する

再利用性が高くていい感じですね!

val seq = Seq(Some(1), None, Some(3))

def noneFirstAsc[T](implicit o: Ordering[T]): Ordering[Option[T]] = Ordering.Option
def noneFirstDesc[T](implicit o: Ordering[T]): Ordering[Option[T]] = noneFirstAsc(o.reverse)
def noneLastDesc[T](implicit o: Ordering[T]): Ordering[Option[T]] = noneFirstAsc.reverse
def noneLastAsc[T](implicit o: Ordering[T]): Ordering[Option[T]] = noneLastDesc(o.reverse)

seq.sorted(noneLastAsc[Int])   == Seq(Some(1), Some(3), None)
seq.sorted(noneFirstDesc[Int]) == Seq(Some(3), Some(1), None)
seq.sorted(noneLastDesc[Int])  == Seq(None, Some(1), Some(3))
seq.sorted(noneLastAsc[Int])   == Seq(None, Some(3), Some(1))

ワンライナーで書く

簡潔に書ける場合もあるので、使う場所、頻度によっては、こちらでもいいかもしれません。

val seq = Seq(Some(1), None, Some(3))

// NoneLastでSomeは昇順
seq.partition(_.nonEmpty) match { case (someSeq, noneSeq) =>
  someSeq.sorted ++ noneSeq
} == Seq(Some(1), Some(3), None)

// NoneLastでSomeは降順
seq.sorted.reverse == Seq(Some(3), Some(1), None)
// or
seq.partition(_.nonEmpty) match { case (someSeq, noneSeq) =>
  someSeq.sorted.reverse ++ noneSeq
} == Seq(Some(3), Some(1), None)

// NoneFirstでSomeは昇順
seq.sorted == Seq(None, Some(1), Some(3))
// or
seq.partition(_.isEmpty) match { case (noneSeq, someSeq) =>
  noneSeq ++ someSeq.sorted
} == Seq(None, Some(1), Some(3))

// NoneFirstでSomeは降順
seq.partition(_.isEmpty) match { case (noneSeq, someSeq) =>
  noneSeq ++ someSeq.sorted.reverse
} == Seq(None, Some(3), Some(1))

他にいい方法があればコメントください!

2
1
2

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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?