开发者

Accessing the next element in list to compare in Scala

开发者 https://www.devze.com 2023-02-28 01:31 出处:网络
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.

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.


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

    }
  }
}


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

精彩评论

暂无评论...
验证码 换一张
取 消