Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 查找数组的最小和最大元素_Scala - Fatal编程技术网

Scala 查找数组的最小和最大元素

Scala 查找数组的最小和最大元素,scala,Scala,我想找到一个数组的最小和最大元素,用于理解。是否可以通过一次数组迭代来找到最小元素和最大元素 我正在寻找一种不使用scala提供的array.min或max的解决方案。val xs:array[Int]=??? val xs: Array[Int] = ??? var min: Int = Int.MaxValue var max: Int = Int.MinValue for (x <- xs) { if (x < min) min = x if (x > max

我想找到一个数组的最小和最大元素,用于理解。是否可以通过一次数组迭代来找到最小元素和最大元素

我正在寻找一种不使用scala提供的array.min或max的解决方案。

val xs:array[Int]=???
val xs: Array[Int] = ???

var min: Int = Int.MaxValue
var max: Int = Int.MinValue

for (x <- xs) {
  if (x < min) min = x
  if (x > max) max = x
}
var min:Int=Int.MaxValue var max:Int=Int.MinValue 对于(x max)max=x }
def findMinAndMax(数组:array[Int])={//非空数组
val initial=(array.head,array.head)//表示最小-最大值的元组
//foldLeft采用结果类型的初始值,在本例中为元组
//foldLeft还具有两个参数的函数。
//“left”参数是累加器(foldLeft->accum为left)
//另一个参数是集合中的值。
//函数2应该返回一个值来替换累加器(在下一次迭代中)
//将从集合中拾取下一个值的时间。
//因此,直到所有值都被迭代,最后返回accum。
数组.foldLeft(初始值){((最小值,最大值),x)=>
如果(x<最小值)(x,最大值)
如果(x>最大值)(最小值,x)为其他值
其他acc
}
}

您可以随时编写自己的
foldLeft
函数-这将保证一次迭代和已知的性能

val array = Array(3,4,62,8,9,2,1)
if(array.isEmpty) throw new IllegalArgumentException // Just so we can safely call array.head

val (minimum, maximum) = array.foldLeft((array.head, array.head)) {  // We start of with the first element as min and max
  case ((min, max), next) =>
    if(next > max) (min, next)
    else if(next < min) (next, max)
    else (min, max)
}

println(minimum, maximum) //1, 62
val数组=数组(3,4,62,8,9,2,1)
如果(array.isEmpty)抛出新的IllegalArgumentException//这样我们就可以安全地调用array.head了
val(minimum,max)=array.foldLeft((array.head,array.head)){//我们从第一个元素开始,第一个元素是min和max
案例((最小值,最大值),下一个)=>
如果(下一个>最大值)(最小值,下一个)
否则如果(下一个<最小值)(下一个,最大值)
其他(最小值、最大值)
}
println(最小值,最大值)//1,62

这里有一个简明易读的解决方案,避免了丑陋的
if
语句:

def minMax(a: Array[Int]) : (Int, Int) = {
  if (a.isEmpty) throw new java.lang.UnsupportedOperationException("array is empty")
  a.foldLeft((a(0), a(0)))
  { case ((min, max), e) => (math.min(min, e), math.max(max, e))}
}
说明:
foldLeft
是Scala中许多集合的标准方法。它允许将累加器传递给回调函数,该函数将为数组的每个元素调用


查看更多详细信息

您可以使用
reduceLeft
函数获取数组[Int]的最小值和最大值

scala> val a = Array(20, 12, 6, 15, 2, 9)
a:Array[Int]=数组(20,12,6,15,2,9)

res:Int=2

scala> a.reduceLeft(_ max _)
res:Int=20


请参阅此链接以了解更多信息和
reduceLeft
方法的示例:

根据其他答案-可能会有一个更通用的解决方案,它适用于其他集合以及
Array
、其他内容以及
Int

def minmax[B >: A, A](xs: Iterable[A])(implicit cmp: Ordering[B]): (A, A) = {
  if (xs.isEmpty) throw new UnsupportedOperationException("empty.minmax")

  val initial = (xs.head, xs.head)

  xs.foldLeft(initial) { case ((min, max), x) => 
    (if (cmp.lt(x, min)) x else min, if (cmp.gt(x, max)) x else max) }
}                                               
例如:

minmax(List(4, 3, 1, 2, 5))              //> res0: (Int, Int) = (1,5)

minmax(Vector('Z', 'K', 'B', 'A'))       //> res1: (Char, Char) = (A,Z)

minmax(Array(3.0, 2.0, 1.0))             //> res2: (Double, Double) = (1.0,3.0)
(也可以使用
cmp.min()
cmp.max()
更简洁地编写此代码,但前提是删除
B>:a
类型绑定,这会使函数不那么通用)。

考虑这一点(对于非空的可订购数组)


我在这次聚会上迟到了,但我是Scala的新手,我想无论如何我都会做出贡献。下面是一个使用尾部递归的解决方案:

@tailrec
def max(list: List[Int], currentMax: Int = Int.MinValue): Int = {
    if(list.isEmpty) currentMax
    else if ( list.head > currentMax) max(list.tail, list.head)
    else max(list.tail,currentMax)
}

在我回顾的所有关于这个问题的答案中,DNA的解决方案是我能找到的最接近“Scala惯用语”的。但是,可以通过以下方式稍微改进:

  • 根据需要执行尽可能少的比较(对于非常大的集合非常重要)
  • 仅使用ordering.lt方法提供理想的排序一致性
  • 避免抛出异常
  • 使代码对那些刚接触和学习Scala的人更具可读性
  • 这些评论应该有助于澄清这些变化

    def minAndMax[B>: A, A](iterable: Iterable[A])(implicit ordering: Ordering[B]): Option[(A, A)] =
      if (iterable.nonEmpty)
        Some(
          iterable.foldLeft((iterable.head, iterable.head)) {
            case (minAndMaxTuple, element) =>
              val (min, max) =
                minAndMaxTuple //decode reference to tuple
              if (ordering.lt(element, min))
                (element, max) //if replacing min, it isn't possible max will change so no need for the max comparison
              else
                if (ordering.lt(max, element))
                  (min, element)
                else
                  minAndMaxTuple //use original reference to avoid instantiating a new tuple
          }
        )
      else
        None
    
    这是一个扩展的解决方案,可以在一次传递中返回2d空间的上下限,同样使用上述优化:

    def minAndMax2d[B >: A, A](iterable: Iterable[(A, A)])(implicit ordering: Ordering[B]): Option[((A, A), (A, A))] =
      if (iterable.nonEmpty)
        Some(
          iterable.foldLeft(((iterable.head._1, iterable.head._1), (iterable.head._2, iterable.head._2))) {
            case ((minAndMaxTupleX, minAndMaxTupleY), (elementX, elementY)) =>
              val ((minX, maxX), (minY, maxY)) =
                (minAndMaxTupleX, minAndMaxTupleY) //decode reference to tuple
              (
                  if (ordering.lt(elementX, minX))
                    (elementX, maxX) //if replacing minX, it isn't possible maxX will change so no need for the maxX comparison
                  else
                    if (ordering.lt(maxX, elementX))
                      (minX, elementX)
                    else
                      minAndMaxTupleX //use original reference to avoid instantiating a new tuple
                , if (ordering.lt(elementY, minY))
                    (elementY, maxY) //if replacing minY, it isn't possible maxY will change so no need for the maxY comparison
                  else
                    if (ordering.lt(maxY, elementY))
                      (minY, elementY)
                    else
                      minAndMaxTupleY //use original reference to avoid instantiating a new tuple
              )
          }
        )
      else
        None
    

    你可以使用
    Vector

    min
    max
    方法,我将从这个链接开始,一些评论可能非常有用嘿,我不想使用min函数。。。我正在寻找不使用min函数的解决方案@Rajeev,我想我满足了你的所有标准,尤其是在处理大量列表时。有关“Scala惯用”解决方案,请参见下面我的答案:能否对代码进行一些解释。我是scala的新手。我觉得很难理解foldLeft是如何工作的,我同意使用acc._1的实现使阅读变得混乱。至少这个解决方案不会执行无关的比较,这在处理一个巨大的列表时很重要。此外,此解决方案不是通用的。关于“Scala惯用”解决方案,请参见下面我的答案:您能为您的解决方案添加一些关于foldLeft和e如何工作的描述吗?UnsupportedOperationException用于完全不同的事情(当整个方法作为一个类型不受支持时,例如不可变集合的remove方法)。通过这种方式,您可以使用
    require(a.nonEmpty,“array is empty”)
    而不是if来存档更简洁的内容。@om nom nom我选择UOE与当前API保持一致(method
    min
    在数组为空时抛出UOE)。等等,
    if
    ,一个非常清楚的单词,你不需要任何东西,只需要一本英语词典就可以理解,这是“难看的”,但是一个带有闭包、模式匹配和函数调用的
    foldLeft
    更好??我喜欢功能范式,但有太多很酷的助手我愿意喝;-)此解决方案将执行无关的比较。如果处理一个巨大的列表,这很重要。更换最小值时,没有理由执行最大值比较。此外,此解决方案不是通用的。关于“Scala惯用”解决方案,请参见下面我的答案:这似乎是一种简洁/惯用的方法。这个答案不正确!如果您仔细阅读原始问题,海报会在一次传递中询问如何收集最小值和最大值。此答案显示了如何在两次传递中收集最小值和最大值,这正是原始海报试图避免的。如果处理大量列表,原始海报请求的单次传递部分很重要。此外,此解决方案不是通用的。看见
    @tailrec
    def max(list: List[Int], currentMax: Int = Int.MinValue): Int = {
        if(list.isEmpty) currentMax
        else if ( list.head > currentMax) max(list.tail, list.head)
        else max(list.tail,currentMax)
    }
    
    def minAndMax[B>: A, A](iterable: Iterable[A])(implicit ordering: Ordering[B]): Option[(A, A)] =
      if (iterable.nonEmpty)
        Some(
          iterable.foldLeft((iterable.head, iterable.head)) {
            case (minAndMaxTuple, element) =>
              val (min, max) =
                minAndMaxTuple //decode reference to tuple
              if (ordering.lt(element, min))
                (element, max) //if replacing min, it isn't possible max will change so no need for the max comparison
              else
                if (ordering.lt(max, element))
                  (min, element)
                else
                  minAndMaxTuple //use original reference to avoid instantiating a new tuple
          }
        )
      else
        None
    
    def minAndMax2d[B >: A, A](iterable: Iterable[(A, A)])(implicit ordering: Ordering[B]): Option[((A, A), (A, A))] =
      if (iterable.nonEmpty)
        Some(
          iterable.foldLeft(((iterable.head._1, iterable.head._1), (iterable.head._2, iterable.head._2))) {
            case ((minAndMaxTupleX, minAndMaxTupleY), (elementX, elementY)) =>
              val ((minX, maxX), (minY, maxY)) =
                (minAndMaxTupleX, minAndMaxTupleY) //decode reference to tuple
              (
                  if (ordering.lt(elementX, minX))
                    (elementX, maxX) //if replacing minX, it isn't possible maxX will change so no need for the maxX comparison
                  else
                    if (ordering.lt(maxX, elementX))
                      (minX, elementX)
                    else
                      minAndMaxTupleX //use original reference to avoid instantiating a new tuple
                , if (ordering.lt(elementY, minY))
                    (elementY, maxY) //if replacing minY, it isn't possible maxY will change so no need for the maxY comparison
                  else
                    if (ordering.lt(maxY, elementY))
                      (minY, elementY)
                    else
                      minAndMaxTupleY //use original reference to avoid instantiating a new tuple
              )
          }
        )
      else
        None
    
    scala> val v = Vector(1,2)
    scala> v.max
    res0: Int = 2
    scala> v.min
    res1: Int = 2