Reputation: 96391
I am trying to define a function, that would take a list and split it down n
without using take
, drop
or grouped
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))
}
Here is what I am thinking. If n < xs.tail.size
we can build up tuple 1 (representing part 1), else we can work on tuple 2 (second part of the list).
The above does not work. It seems that it does not like the ::
when I am constructing part of a tuple.
Am I approaching this the right way?
Example: mySplit(3, (1 to 5).toList)
should return (List(1,2,3), List(4,5))
Upvotes: 1
Views: 652
Reputation: 1713
If you still want to split large lists, here is a tail recursive variant. Its also faster:
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)
}
Upvotes: 1
Reputation: 340743
Here is my take, rewritten from scratch:
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)
}
}
}
Or alternatively and shorter:
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)
}
}
}
Upvotes: 3