'Choosing the last element of a list

scala> last(List(1, 1, 2, 3, 5, 8))
res0: Int = 8

for having a result above, I wrote this code:

val yum = args(0).toInt
val thrill: 

def last(a: List[Int]): List[Int] = {
     println(last(List(args(0).toInt).last)
     }

What is the problem with this code?



Solution 1:[1]

You can use last, which returns the last element or throws a NoSuchElementException, if the list is empty.

scala> List(1, 2, 3).last
res0: Int = 3

If you do not know if the list is empty or not, you may consider using lastOption, which returns an Option.

scala> List().lastOption
res1: Option[Nothing] = None

scala> List(1, 2, 3).lastOption
res2: Option[Int] = Some(3)

Your question is about List, but using last on a infinite collection (e.g. Stream.from(0)) can be dangerous and may result in an infinite loop.

Solution 2:[2]

Another version without using last (for whatever reason you might need it).

def last(L:List[Int]) = L(L.size-1)

Solution 3:[3]

You should better do:

 val a = List(1,2,3) //your list
 val last = a.reverse.head

Cleaner and less error-prone :)

Solution 4:[4]

Albiet this is a very old question, it might come handy that the performance impact of head and last operations seems to be laid out here http://docs.scala-lang.org/overviews/collections/performance-characteristics.html.

Solution 5:[5]

The recursive function last should following 2 properties. Your last function doesn't have any of them.

  • Requirement #1. An exit condition that does not call recursive function further.

  • Requirement #2. A recursive call that reduces the elements that we began with.

Here are the problems I see with other solutions.

  1. Using built in function last might not be an option in interview questions.
  2. Reversing and head takes additional operations, which the interviewer might ask to reduce.
  3. What if this is a custom linked list without the size member?

I will change it to as below.

def last(a: List[Int]): Int = a match {
  //The below condition defines an end condition where further recursive calls will not be made. requirement #1
  case x::Nil => x
  //The below condition reduces the data - requirement#2 for a recursive function.
  case x:: xs => last(xs)
}

last(List(1,2,3))

Result

res0: Int = 3

Solution 6:[6]

In these types of questions the useful take and takeRight are often overlooked. Similar to last, one avoids the slow initial reversing of a list, but unlike last, can take the last (or first) n items as opposed to just a single one:

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

scala> myList.takeRight(2)
res0: List[Int] = List(2, 3)

scala> myList.takeRight(1)
res1: List[Int] = List(3)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Jus12
Solution 3 Pere Villega
Solution 4 Marton Tatai
Solution 5 Ravi
Solution 6 nondeterministic