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

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.
主站蜘蛛池模板: 宁化县| 尚志市| 安庆市| 溧水县| 莱阳市| 永顺县| 保康县| 右玉县| 苍梧县| 宿州市| 涿鹿县| 沐川县| 郁南县| 监利县| 酉阳| 女性| 东至县| 阿鲁科尔沁旗| 正宁县| 通渭县| 保康县| 库伦旗| 独山县| 绩溪县| 应城市| 镇远县| 桂林市| 静海县| 油尖旺区| 容城县| 柳林县| 保定市| 象山县| 大名县| 正阳县| 汉源县| 贵港市| 囊谦县| 徐闻县| 布拖县| 建德市|