How to sort case classes with [String] option in alphabetical order, ignoring None?

Given List[Foo]where it Foois defined as:

case class Foo(bar: Option[String])

What is the best way to find Foowith the first barin alphabetical order?

For example, if I had:

val l = List(Foo(None), Foo(Some("xyz")), Foo(Some("abc")))

I would like to return Foo(Some("abc"))

+4
source share
5 answers
   list.filter(_.bar.isDefined) match {
      case Nil => Foo(None)
      case l => l.minBy(_.bar)
   }

Or, if there will always be at least one non-empty option, then simply list.filter(_.bar.isDefined).minBy(_.bar)

This is (slightly) better than sorting because it is linear and does not require data structure isolation.

Another possibility that is even (a little) more effective (but a little more),

list.reduceOption { 
    case (Foo(None), x) => x
    case (x, Foo(None)) => x
    case (Foo(Some(x)), Foo(Some(y))) => if ( x < y ) Foo(Some(x)) else Foo(Some(y))
}
+2
source

sortBy, collectFirst, , None:

l.sortBy(_.bar).collectFirst { case x @ Foo(Some(_)) => x }

, Option[Foo], None, None. Some(first matching element).

, Option, get .

+2

, . :

 case class Foo(bar: Option[String])
 val l = List(Foo(None), Foo(Some("xyz")), Foo(Some("abc")))

  val foo = l.foldLeft(Foo(None)) {
    (acc, elem) => (for {
      elemB  <- elem.bar
      accB <- acc.bar
      smaller = if( elemB <  accB) elem else acc
    } yield smaller)
      .getOrElse(elem)
  }

  System.out.println(foo.bar)
+1

foldLeft. , :

import Ordering.Implicits._

val res = l.foldLeft(Foo(None))((res, foo) =>
  if (res.bar.isEmpty) foo
  else if (foo.bar.isEmpty) res
  else if (res.bar < foo.bar) res
  else foo)

println(res) // Foo(Some(abc))
0

.

l.filter {_ match {
    case Foo(None) => false
    case _ => true
  }
}.minBy(_.bar)
0

Source: https://habr.com/ru/post/1568383/


All Articles