1

我正在尝试定义一个函数,该函数将获取一个列表并将其拆分n而不使用take,dropgrouped

  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(列表的第二部分)。

以上不起作用。似乎它不喜欢::我在构建元组的一部分时。

我以正确的方式接近这个吗?

示例: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 回答