yAsH
yAsH

Reputation: 3405

Scala - Combine two lists in an alternating fashion

How do I merge 2 lists in such a way that the resulting list contains the elements of 2 lists in alternating fashion in Scala.

Input:

val list1 = List("Mary", "a", "lamb")

val list2 = List("had", "little")

Output:

List("Mary", "had", "a", "little", "lamb")

Upvotes: 13

Views: 5233

Answers (4)

arkonautom
arkonautom

Reputation: 958

val list1 = List("Mary", "a", "lamb")
val list2 = List("had", "little")

def merge1(list1: List[String], list2: List[String]): List[String] = {
    if (list1.isEmpty) list2
    else list1.head :: merge(list2, list1.tail)
}

def merge2(list1: List[String], list2: List[String]): List[String] = list1 match {
    case List() => list2
    case head :: tail => head :: merge(list2, tail)
} 

merge1(list1, list2)
merge2(list1, list2)
//> List[String] = List(Mary, had, a, little, lamb)

Upvotes: 5

yan
yan

Reputation: 20992

What you're looking for is usually called "intersperse" or "intercalate" and there are a few ways to do it:

def intersperse[A](a : List[A], b : List[A]): List[A] = a match {
  case first :: rest => first :: intersperse(b, rest)
  case _             => b
}

You can also use scalaz

import scalaz._
import Scalaz._

val lst1 = ...
val lst2 = ...

lst1 intercalate lst2

Edit: You can also do the following:

lst1.zipAll(lst2,"","") flatMap { case (a, b) => Seq(a, b) }

Come to think of it, I believe the last solution is my favorite since it's most concise while still being clear. If you're already using Scalaz, I'd use the second solution. The first is also very readable however.

And just to make this answer more complete, adding @Travis Brown's solution that is generic:

list1.map(List(_)).zipAll(list2.map(List(_)), Nil, Nil).flatMap(Function.tupled(_ ::: _))

Upvotes: 21

Daarx
Daarx

Reputation: 134

You could do something like this:

def alternate[A]( a: List[A], b: List[A] ): List[A] = {
    def first( a: List[A], b: List[A] ): List[A] = a match {
        case Nil => Nil
        case x :: xs => x :: second( xs, b )
    }

    def second( a: List[A], b: List[A] ): List[A] = b match {
        case Nil => Nil
        case y :: ys => y :: first( a, ys )
    }

    first( a, b )
}    

Upvotes: 1

Ankur
Ankur

Reputation: 33657

list1.zipAll(list2,"","").flatMap(_.productIterator.toList).filter(_ != "")

Upvotes: 1

Related Questions