Given an element in a sequence, how to get the previous element?

Say I have a Scala List("apple", "orange", "banana", "chinese gooseberry") *. I want to search this list and return either the previous item in the list with respect to the item that I already have.

For example: getPrevious(fruit: String, fruits: List[String]): Option[String] should return

  • Some("apple") if I call it with fruit arg "orange" ;
  • Some("banana") for "chinese gooseberry" ;
  • None if I call it using "apple" (the previous item does not exist) or "potato" (not on the list).

Easily made for real, but how can I do it in an elegant, functional way? The best I can think of is the following:

 def previous(fruit: String, fruits: List[String]): Option[String] = fruits.sliding(2) .filter { case List(previous, current) => current == fruit } .toList .headOption .map { case List(previous, current) => previous } 

It works, but it is not elegant and not efficient. I especially hate filter toList iterator toList . How can I improve it?

(* as an aside, is List best collection used to iterate sliding ?)

+6
source share
3 answers

I think this is the case when only the correct recursion and pattern matching are efficient and easier to read:

 @annotation.tailrec def getPrevious(fruit: String, fruits: List[String]): Option[String] = fruits match { case Nil => None case x :: `fruit` :: _ => Some(x) case _ :: xs => getPrevious(fruit, xs) } 
+8
source

Here's a shorter version using collectFirst :

 def previous(fruit: String, fruits: List[String]): Option[String] = fruits.sliding(2).collectFirst{ case List(previous, `fruit`) => previous} 

Pay attention to the anchor points surrounding fruit to match the value of the parameter. Using collectFirst also stop on the first match, rather than running through the entire iterator with filter .

+11
source

The first simple solution that comes to mind is:

 import scala.util.Try def previous(fruit: String, fruits: List[String]) = Try(fruits(fruits.indexOf(fruit) - 1)).toOption 

Of course, should be more effective.

+1
source

Source: https://habr.com/ru/post/973139/


All Articles