官术网_书友最值得收藏!

Getting the nth element of a list

A list holds a certain number of elements. The first element is at index 0, and the second element at index 1. If the index is out of range, we get an exception.

We will write a method to find the nth element of a list. This method will return an option. If n is out of bounds, we will return None. Otherwise, we will return Some(elem). Let's look at the code and then a diagram to understand it better:

import scala.annotation.tailrec
object NthElemOfList extends App {
 def nth(list: List[Int], n: Int): Option[Int] = {
  @tailrec
  def nthElem(list: List[Int], acc: (Int, Int)): Option[Int] = list match {
    case Nil => None
    case head :: tail => {
     if (acc._1 == acc._2)     // 1
     Some(head)    
    else
      nthElem(tail, (acc._1 + 1, acc._2))     // 2
   }
   }
  nthElem(list, (0, n))   // 3
 }
 val bigList = 1 to 100000 toList  // 4
 println(nth(List(1, 2, 3, 4, 5, 6), 3).getOrElse("No such elem"))
 println(nth(List(1, 2, 3, 4, 5, 6), 300).getOrElse("No such elem"))
 println(nth(bigList, 2333).getOrElse("No such elem"))
}

Here is a diagrammatic representation of the flow:

Figure: 3.4: Conceptual stack frames

The description of the preceding diagram is as follows:

  • Our accumulator is a pair. The first element is a running index and holds the index of the current node, starting from 0. The second element is always fixed at n.
  • If index == n, we have found the element. Now, we will return it wrapped in a some. else we increase the running index and recursively call the method again on the tail of the list.
  • We wish to hide the accumulator from the client code. Keeping an accumulator is an implementation detail.
  • We will test the index with a very big list as @tailrec is in effect, the TCO kicks in and we don't get any stack overflows. Try to rewrite the preceding code without using a pair of element for the accumulator. Compare your version with it and check which one is better.

The following are a few points that we need to ponder:

  • Could we simply use acc as Int? Do we really need the pair?
  • Try writing the code so that we decrement the accumulator instead of incrementing it.
主站蜘蛛池模板: 武定县| 弥勒县| 麟游县| 建昌县| 兴化市| 兰考县| 博客| 乌鲁木齐县| 厦门市| 通榆县| 司法| 桦甸市| 宣化县| 三都| 景泰县| 西和县| 紫云| 东兰县| 内乡县| 北宁市| 建平县| 天气| 上虞市| 惠来县| 香港| 彭山县| 澄迈县| 万年县| 天峨县| 尤溪县| 麟游县| 巴楚县| 泸定县| 福清市| 县级市| 许昌县| 绥阳县| 黑水县| 台湾省| 牡丹江市| 金溪县|