简体   繁体   中英

Accessing the next element in list to compare in 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")

How about sliding?

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

//List(1, 2)
//List(2, 3)
//List(3, 4)

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.

This would be better handled by recursing over the list , instead of iterating through the elements , since elements don't know anything about the list.

For example:

def recurse[T](list: List[T]): Unit = list match {
    case List(x, y, _*) if x == y => 
        println("same")
        recurse(list.tail)
    case Nil =>
    case _   => recurse(list.tail)
}

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)
      }

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

scala> (xs, xs.tail).zip.foreach(println)
(1,3)
(3,5)
(5,4)

scala>

As in Scala 2.11.7 the following are valid:

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

1) Zip the tail

scala> xs.zip(xs.tail)
res0: List[(Int, Int)] = List((1,2), (2,3), (3,4))

2) Slide the window

scala> xs.sliding(2)
res1: Iterator[List[Int]] = non-empty iterator

list.tail.head

gives the next element if you want to go through all the elements from the front of the list. This is because the head is the front-most element and tail is the rest of the list.

scala> val li = List (3, 4, 5) 
li: List[Int] = List(3, 4, 5)

scala> li.tail.head 
res74: Int = 4

If you don't want to compare just a single element, but a sequence of arbitrary length, you can do it in recursive function:

def compAdjectent (l: List [Int]) : Boolean = l match {
  case Nil => false 
  case x :: Nil => false 
  case x :: y :: xs => if (x.equals (y)) true else compAdjectent (y :: xs)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM