James Raitsev
James Raitsev

Reputation: 96391

How to split a List to tuples?

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

Answers (2)

idonnie
idonnie

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

Tomasz Nurkiewicz
Tomasz Nurkiewicz

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

Related Questions