1

、またはnを使用せずにリストを取得して分割する関数を定義しようとしています。takedropgrouped

  def mySplit[X](n: Int, xs: List[X]): (List[X], List[X]) = {
    if (n <= 0) (Nil, xs)
    else
    if (n >= xs.size) (xs, Nil)
    else
    if (n < xs.tail.size) (xs.head :: mySplit(n, xs.tail), Nil) 
                     else (Nil, xs.head :: mySplit(n, xs.tail))
  }

これが私が考えていることです。n < xs.tail.sizeタプル1(パート1を表す)を構築できる場合は、タプル2(リストの2番目の部分)で作業できます。

上記は機能しません。::タプルの一部を作成しているときは気に入らないようです。

私はこれに正しい方法でアプローチしていますか?

例:mySplit(3, (1 to 5).toList)戻る必要があります(List(1,2,3), List(4,5))

4

2 に答える 2

3

これが私の見解です。最初から書き直しました。

def mySplit[X](n: Int, xs: List[X]): (List[X], List[X]) = {
  xs match {
    case Nil => (Nil, Nil)
    case head :: tail =>
      if(n == 0)
        (Nil, xs)
      else
        mySplit(n - 1, tail) match {
          case (before, after) =>
            (head :: before, after)
        }
  }
}

または、代わりに、より短い:

def mySplit[X](n: Int, xs: List[X]): (List[X], List[X]) = {
  n match {
    case 0 => (Nil, xs)
    case s =>
      mySplit(s - 1, xs.tail) match {
        case (before, after) =>
          (xs.head :: before, after)
      }  
  }
}
于 2013-01-28T22:10:41.913 に答える
1

それでも大きなリストを分割したい場合は、末尾再帰のバリアントを次に示します。また、より高速です。

import scala.annotation.tailrec
def mySplit[X](n: Int, xs: List[X]): (List[X], List[X]) = {
  require(n >= 0)
  if (n > 0) {
    var result: (List[X], List[X]) = null
    @tailrec
    def mySplit0(n: Int, l: List[X], r: List[X]): Unit = r match {
      case h :: t if (n > 0) => mySplit0(n - 1, h :: l, t)
      case _ => result = (l.reverse, r)
    }
    mySplit0(n, Nil, xs)
    result
  } else (Nil, xs)
}
于 2013-01-29T01:04:17.763 に答える