Scala - 按可选字段排序,None 值最后

Scala - Sort by Optional fields, with None value last

我有以下 class :

final case class PowerDetails (
  [...],
  label: String,
  title: String,
  category: String,
  idCategory: Option[String],
  numCategory: Option[Int]
)

我需要像这样对 PowerDetails 列表进行排序:

Elements having a value for idCategory and numCategory should be before the None , and ordered by idCategory and then numCategory. As for the None values, they need to be ordered by the fields category , title , label.

如果可能,我想避免延长 Ordered

final case class PowerDetails (

   ...

) extends Ordered[PowerDetails] {

    override def compare(that: PowerDetails): Int = {
       // Define here the comparison
    }

}

我尝试创建如下所示的排序,然后使用 sorted 函数,但我得到的是 NullPointerException

  implicit val orderingPowers = optionOrdering.thenComparing(ordering)

  val ordering: Ordering[PowerDetails] = Ordering[(String, String, String)]
    .on[PowerDetails](powerDetail =>
      ( powerDetail.category, powerDetail.title, powerDetail.label))

  val optionOrdering : Ordering[PowerDetails] = Ordering[(Option[String], Option[Int])]
    .on[PowerDetails](powerDetail =>
      (powerDetail.idCategory, powerDetail.numCategory))

你能帮我看看怎么做吗? 谢谢。

这对你有用吗?

implicit val PDOrd :Ordering[PowerDetails] = Ordering.by(
  pd => (pd.idCategory.getOrElse("~~~~")
       , pd.numCategory.getOrElse(Int.MaxValue)
       , pd.category
       , pd.title
       , pd.label ))

无可否认,"~~~~" 并不是 String 世界的尽头,但它在大多数情况下都应该有效。

这是另一种方法,它也使用 Ordering.by 和选项的 isEmpty,利用 false < true 实现所需的 Some/None 排序:

final case class PowerDetails (
  field1: String,
  field2: Int,
  label: String,
  title: String,
  category: String,
  idCategory: Option[String],
  numCategory: Option[Int]
)

implicit val PDOrderer: Ordering[PowerDetails] = Ordering.by{
  case PowerDetails(_, _, label, title, cat, idCat, numCat) =>
    (idCat.isEmpty, idCat, numCat.isEmpty, numCat, cat, title, label)
}