Min/max with Option[T] for possibly empty Seq?

后端 未结 10 935
别那么骄傲
别那么骄傲 2021-01-31 14:03

I\'m doing a bit of Scala gymnastics where I have Seq[T] in which I try to find the \"smallest\" element. This is what I do right now:

val leastOrNo         


        
相关标签:
10条回答
  • 2021-01-31 14:22

    You could always do something like:

    case class Foo(num: Int)
    
    val foos: Seq[Foo] = Seq(Foo(1), Foo(2), Foo(3))
    val noFoos: Seq[Foo] = Seq.empty
    
    def minByOpt(foos: Seq[Foo]): Option[Foo] =
      foos.foldLeft(None: Option[Foo]) { (acc, elem) => 
        Option((elem +: acc.toSeq).minBy(_.num)) 
      }
    

    Then use like:

    scala> minByOpt(foos)
    res0: Option[Foo] = Some(Foo(1))
    
    scala> minByOpt(noFoos)
    res1: Option[Foo] = None
    
    0 讨论(0)
  • 2021-01-31 14:22

    For scala < 2.13

    Try(seq.minBy(_.something)).toOption
    

    For scala 2.13

    seq.minByOption(_.something)
    
    0 讨论(0)
  • 2021-01-31 14:22

    In Haskell you'd wrap the minimumBy call as

    least f x | Seq.null x = Nothing
              | otherwise  = Just (Seq.minimumBy f x) 
    
    0 讨论(0)
  • 2021-01-31 14:27

    I have the same problem before, so I extends Ordered and implement the compare function. here is example:

     case class Point(longitude0: String, latitude0: String)  extends Ordered [Point]{
    
      def this(point: Point) = this(point.original_longitude,point.original_latitude)
      val original_longitude = longitude0
      val original_latitude = latitude0
    
      val longitude = parseDouble(longitude0).get 
      val latitude = parseDouble(latitude0).get  
    
      override def toString: String = "longitude: " +original_longitude +", latitude: "+ original_latitude
    
      def parseDouble(s: String):  Option[Double] = try { Some(s.toDouble) } catch { case _ => None }
    
      def distance(other: Point): Double =
        sqrt(pow(longitude - other.longitude, 2) + pow(latitude - other.latitude, 2))
    
     override def compare(that: Point): Int = {
      if (longitude < that.longitude)
        return -1
      else if (longitude == that.longitude && latitude < that.latitude)
        return -1
      else
        return 1
     }
    }
    

    so if I have a seq of Point I can ask for max or min method

      var points =  Seq[Point]()
    
    val maxPoint = points.max
    val minPoint = points.min
    
    0 讨论(0)
  • 2021-01-31 14:28

    A safe, compact and O(n) version with Scalaz:

    xs.nonEmpty option xs.minBy(_.foo)
    
    0 讨论(0)
  • 2021-01-31 14:28

    Hardly an option for any larger list due to O(nlogn) complexity:

    seq.sortBy(_.something).headOption
    
    0 讨论(0)
提交回复
热议问题