4

I have following lists -

val A = List(("A","B","C","D"),("A1","B1","C1","D1"),("A2","B2","C2","D2"))

and

val B = List(("P","Q","R","S","T"),("P1","Q1","R1","S1","T1"),("P2","Q2","R2","S2","T2"),("P3","Q3","R3","S3","T3"))

I want to merge 1st element of list A with first element of list B and so on. here list A have 3 elements and B have 4. I want to consider number of elements in list A while merging.

output as below

val combineList = List(("A","B","C","D","P","Q","R","S","T"),("A1","B1","C1","D1","P1","Q1","R1","S1","T1"),
        ("A2","B2","C2","D2","P2","Q2","R2","S2","T2"))
Vishwas
  • 6,967
  • 5
  • 42
  • 69

3 Answers3

7

If you can use shapeless, then you can simply do

scala> import shapeless.syntax.std.tuple._
scala> A.zip(B).map{case(a,b) => a ++ b}
res1: List[(String, String, String, String, String, String, String, String, String)] = List((A,B,C,D,P,Q,R,S,T), (A1,B1,C1,D1,P1,Q1,R1,S1,T1), (A2,B2,C2,D2,P2,Q2,R2,S2,T2))

It will work on arbitrary size of tuples.

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
mohit
  • 4,968
  • 1
  • 22
  • 39
  • Sorry. As I understand you mean `shapeless` library (https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#hlist-style-operations-on-standard-scala-tuples). – user5102379 Jan 10 '15 at 07:16
  • is there a non-shapeless way to answer the OP's question for **arbritrary** tuples? – Kevin Meredith Jan 10 '15 at 16:13
  • @KevinMeredith - There is not an easy way. Scala does not provide a built in method to add or remove an element from a Tuple(A list is a more appropriate data structure for that while maintaining type safety). A non shapeless way will include first calculating size of the two tuples to determine what will be the -arity of the Tuple(the easiest part) After that create a tuple by calling the appropriate Tuple class(Tuple2, Tuple6 etc) and feed the values programatically. – mohit Jan 10 '15 at 16:46
1
A.zip(B).map { case ((a,b,c,d), (p,q,r,s,t)) => (a,b,c,d,p,q,r,s,t) }
Dima
  • 39,570
  • 6
  • 44
  • 70
  • Will this work for tuples with different sizes i.e, if tuples are of size 5 and 6 or 2 and 4 ? – Soumya Simanta Jan 09 '15 at 13:23
  • Different tuples are different types, so, no. You'd have to write a different function for that ... or use shapeless, like @mohit suggested in his answer, although, that would not be my advice. – Dima Jan 09 '15 at 14:23
-1

First zip tuples in sequnces:

val lists = for {i <- 0 until A.length
     a = A(i)
     b = B(i)
} yield (a.productIterator ++ b.productIterator).toList

Next define converter from Seq back to Product:

def toTuple(seq: Seq[_]): Product = {
  val clz = Class.forName("scala.Tuple" + seq.size)
  clz.getConstructors()(0).newInstance(seq.map(_.asInstanceOf[AnyRef]): _*).asInstanceOf[Product]
}

And finally do map:

lists.map(toTuple)

This code does not consider different arity of input lists and tuple size's limitation.

Sergii Lagutin
  • 10,561
  • 1
  • 34
  • 43
  • This results in `List[Product]`, not `List[(String,String,String,String,String,String,String,String,String)]` – Dima Jan 09 '15 at 14:26
  • @Dima This code is about tuples of variadic length. And your comment is about tuples of fixed arity. – Sergii Lagutin Jan 09 '15 at 14:56
  • Huh? Where do you see anything about "variadic length" in the question? In general `tuple` *means* fixed arity. There is a different name for "tuples of variafic length": they are called lists :) – Dima Jan 09 '15 at 15:07