Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing the next element in list to compare in Scala

Tags:

list

scala

I'm new to Scala and i was wondering how you can call the next element of the list because I am trying to compare the current element with the adjacent one. Given x as the current element, I tried similar to java, x+1 but that didnt work. Any help?

for (x <- list; if (x == (next adj. element))) println("same")
like image 670
Dan Avatar asked Apr 20 '11 07:04

Dan


3 Answers

How about sliding?

val list = List(1,2,3,4)
list.sliding(2).foreach(println)

//List(1, 2)
//List(2, 3)
//List(3, 4)
like image 110
Landei Avatar answered Nov 07 '22 00:11

Landei


The canonical ways to do this in a for loop would be:

scala> val xs = List(1,2,3,4,3,2)
xs: List[Int] = List(1, 2, 3, 4, 3, 2)

scala> for (List(left,right) <- xs.sliding(2) if (left < right)) println(left + " < " + right)
1 < 2
2 < 3
3 < 4

scala> for ((left,right) <- (xs zip xs.tail) if (left < right)) println(left + " < " + right)
1 < 2
2 < 3
3 < 4

(Incidentally, you're probably better off putting the if statement outside rather than inside the for comprehension in this example.)

If you have indices instead of values, you just dereference them using the same pattern. Personally, I don't find this pattern very clear or useful. It's slow, has weird corner-cases with lists that aren't full, and it's hard to follow what's going on. Instead, I define

class PairedIterable[A](it: Iterable[A]) {
  def foreachpair(f: (A,A) => Unit) = {
    val i = it.iterator
    if (i.hasNext) {
      var prev = i.next
      while (!ans && i.hasNext) {
        val x = i.next
        f(prev,x)
        prev = x
      }
    }
  }
}
implicit def iterable_has_pairs[A](it: Iterable[A]) = new PairedIterable(it)

which can then be used like so:

scala> xs.foreachpair((left, right) => if (left < right) println(left + " < " + right))
1 < 2
2 < 3
3 < 4

Variants "forallpair", "existspair", and "findpair" are particularly useful.

like image 7
Rex Kerr Avatar answered Nov 06 '22 23:11

Rex Kerr


As an option you may use match and recursion instead of for:

object Test {
  def main(args: Array[String]) {
    val list = List(1, 5, 3)
    loop(list)
  }

  def loop(list: List[Int]) {
    list match {
      case Nil => println("Empty list")
      case x :: Nil => println("last " + x)
      case x :: tail => {
        println(x + " - " + tail.head)
        loop(tail)
      }

    }
  }
}
like image 3
tonek Avatar answered Nov 06 '22 22:11

tonek