5

Does anyone know how to get the index of the largest element from this function:

The programming-language is scala

def indexOfLargestElement(arr: Array[Int]): Int = 

For example:

indexOfLargestElement(Array( 1, -6, 4, 5, 2, -1) ) == 3

I don't get it -.-

Thanks for your help!

Peter Elliott
  • 3,273
  • 16
  • 30
  • Possible duplicate of [How can I find the index of the maximum value in a List in Scala?](http://stackoverflow.com/questions/14011181/how-can-i-find-the-index-of-the-maximum-value-in-a-list-in-scala) – Suma Apr 12 '16 at 19:48
  • `arr.indices.maxBy(arr)` – jwvh Oct 21 '20 at 06:06

6 Answers6

10

Here's how to do it with a single traversal:

def indexOfLargest(array: Seq[Int]): Int = {
    val result = array.foldLeft(-1,Int.MinValue,0) {
        case ((maxIndex, maxValue, currentIndex), currentValue) =>
            if(currentValue > maxValue) (currentIndex,currentValue,currentIndex+1)
            else (maxIndex,maxValue,currentIndex+1)
        }
    result._1
}

This will use a tuple of (index of maximum element known; value of maximum element; curent index) to hold the data in the loop.

Alex Yarmula
  • 10,477
  • 5
  • 33
  • 32
  • Thanks for the answers they helped me a lot :) just one more question .. would it be possible to do this with for-loop? –  Mar 22 '13 at 10:59
6
// val l = Array(1, -6, 4, 5, 2, -1)
l.indexOf(l.max)
Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190
barczajozsef
  • 473
  • 5
  • 11
  • 2
    At most two traversals. The second traversal bails out as soon as it locates the element. – hughw Apr 13 '13 at 17:28
5
scala> :paste
// Entering paste mode (ctrl-D to finish)

@annotation.tailrec final def indexOfLargestElement(a: Array[Int], i: Int = -1, mi: Int = -1, ma: Int = Int.MinValue): Int = {
  val i1 = i + 1
  if (i1 < a.length) {
    val ai1 = a(i1)
    if (ai1 >= ma) indexOfLargestElement(a, i1, i1, ai1)
    else indexOfLargestElement(a, i1, mi, ma)
  } else mi
}

// Exiting paste mode, now interpreting.

indexOfLargestElement: (a: Array[Int], i: Int, mi: Int, ma: Int)Int

scala> indexOfLargestElement(Array(1, -6, 4, 5, 2, -1))
res0: Int = 3

scala> indexOfLargestElement(Array())
res1: Int = -1

scala> indexOfLargestElement(Array(Int.MinValue))
res2: Int = 0
Andriy Plokhotnyuk
  • 7,883
  • 2
  • 44
  • 68
  • 3
    Why all the downvotes? It's a correct solution (and also very fast, though not the simplest to understand). – Rex Kerr Mar 21 '13 at 17:30
  • I find it as understandable as @alexwriteshere's, the logic is about the same, only expressed imperatively. – pagoda_5b Mar 21 '13 at 17:53
4

I'm not sure what is the performance, because there may be expensive implicit conversions and I can't tell which sorting algorithm is acually used.

Still this is it

scala> val arr = Array( 1, -6, 4, 5, 2, -1)
arr: Array[Int] = Array(1, -6, 4, 5, 2, -1)

scala> arr.zipWithIndex.maxBy(_._1)._2
res1: Int = 3
pagoda_5b
  • 7,333
  • 1
  • 27
  • 40
  • this does `reduceLeft((x, y) => if (cmp.gteq(f(x), f(y))) x else y)` where `implicit cmp: Ordering[B]` (See `TraversableOnce`) – sourcedelica Mar 22 '13 at 21:37
  • @sourcedelica your suggestions will return the max element, not the index... or am I missing something? – pagoda_5b Mar 24 '13 at 08:29
0

My solution is very basic, but easy to understand

/** 
 * Returns the max index or -1 if there is no max index
 */
def getMaxIndex(array: Array[Int]): Int = {
  var maxIndex = -1
  var max = Int.MinValue
  for {
    index <- 0 until array.length
    element <- array
  } {
    if (element > max) {
      max = element
      maxIndex = index
    }
  }
  maxIndex
}

It is pretty much the same as

/** 
 * Returns the max index or -1 if there is no max index
 */
def getMaxIndex(array: Seq[Int]): Int = {
    val startIndex = 0
    val result = array.foldLeft(-1, Int.MinValue, startIndex) {
        case ((maxIndex, max, index), element) => {
            if(element > max) (index, element, index+1)
            else (maxIndex, max, index+1)
        }
    }
    result._1
}
0

Same solution and some of the ones above but a little more tail recursive:

  def getMaxIndex(a: Array[Double]): Int = {
    val l = a.length

    def findMax(v: Double, k: Int, i: Int): Int = {
      if (i < l) {
        if (v < a(i)) findMax(a(i), i, i + 1) else findMax(v, k, i + 1)
      } else k
    }

    findMax(Double.NegativeInfinity, -1, 0)
  }

The true tail recursion makes the process easier to understand. It is also easier to call, just taking the matrix itself and it doesn't modify the matrix in anyway making it fast. Only visits each element once.

Basically a simpler version of Alex Yarmula and Andriy Plokhotnyuk solutions.

BGW
  • 75
  • 5