arraysscalasequencesliding

How to keep track of the index in an Array.sliding


When using a sliding function on an Array in scala, what is a correct way to track the index of the sliding subarray in terms of the original array?

// Initialize some data
val bigArray = List(2, 3, 4, 2, 3, 6, 8, 4, 5).toArray
val n:Int = 5

// Slide through the big array
for (smallArray <- bigArray.sliding(n)) {
  val thirdValue:Int = smallArray(3)
  val k = (bigArray zip smallArray) lastIndexWhere { case (x, y) => x < y }
  if (bigArray(k+1) >= thirdValue) {
    println(bigArray.toList.toString + 
      " has "
      + bigArray(k+1)
      + " >= " 
      + thirdValue 
      + " in "
      + smallArray.toList.toString
      + " at index "
      + k+1)
  }

Now I know that

val k = (bigArray zip smallArray) lastIndexWhere { case (x, y) => x < y }

is incorrect. What is the correct way to track where the smallArray is in terms of the original bigArray?

What I'm getting is

List(2, 3, 4, 2, 3, 6, 8, 4, 5) has 2 >= 2 in List(2, 3, 4, 2, 3) at index -11
List(2, 3, 4, 2, 3, 6, 8, 4, 5) has 6 >= 3 in List(3, 4, 2, 3, 6) at index 41
List(2, 3, 4, 2, 3, 6, 8, 4, 5) has 6 >= 6 in List(4, 2, 3, 6, 8) at index 41
List(2, 3, 4, 2, 3, 6, 8, 4, 5) has 6 >= 4 in List(3, 6, 8, 4, 5) at index 41

and I need

List(2, 3, 4, 2, 3, 6, 8, 4, 5) has 6 >= 2 in List(2, 3, 4, 2, 3) at index 5
List(2, 3, 4, 2, 3, 6, 8, 4, 5) has 8 >= 3 in List(3, 4, 2, 3, 6) at index 6

Update

I couldn't get map to work with the tuple2(Int, Int) that came from head in the accepted answer, but the mention of zipWithIndex got me there, so I accepted the helpful answer. This is what I ended up with:

for (zipArray <- bigArray.slice(0, bigArray.length - 1).zipWithIndex.sliding(n)) {
  val j = zipArray.head._2
  val k = zipArray.last._2
  val smallArray = bigArray.slice(j, k)
  val thirdValue:Int = smallArray(3)
  if (bigArray(k+1) >= thirdValue) {
    println(bigArray.toList.toString +
      " has "
      + bigArray(k+1)
      + " >= "
      + thirdValue
      + " in "
      + smallArray.toList.toString
      + " at index "
      + (k+1) )
  }
}

which yields:

List(2, 3, 4, 2, 3, 6, 8, 4, 5) has 6 >= 2 in List(2, 3, 4, 2) at index 5
List(2, 3, 4, 2, 3, 6, 8, 4, 5) has 8 >= 3 in List(3, 4, 2, 3) at index 6

Solution

  • You can use zipWithIndex before sliding:

    for (smallArrayWithIndex <- bigArray.zipWithIndex.sliding(n)) {
        val startingIndex = smallArrayWithIndex.head.map { case (_, index) => index }
        val smallArray = smallArrayWithIndex.map { case (e, _) => e }
        println("smallArray starts at index " + index + " and contains " + smallArray)
    }