1

I have a function which is returning List<String[]> , I can modify it to return something else also, In scale the function I am calling is expecting input as: Seq[Product]

I am getting following error:

[scalac-2.11]  found   : List[Array[String]]
[scalac-2.11]  required: Seq[Product]

I am new to scala, how can I do the same?

The api I need to call is expecting input like:

 Seq( ("id", "string", "id", "string"), ("my_date", "string", "my_date", "string") )) ) 
Vivek Goel
  • 22,942
  • 29
  • 114
  • 186
  • It seems odd that your expected datatype is `Product`. That's a very base-level datatype, quite close to `Any` (the Scala equivalent of `Object`). Are you sure `Product` is the input type you want? – Lasf Aug 28 '18 at 23:21
  • I am glue a glue api, which expect input in following format: applyMapping( Seq( ("id", "string", "id", "string"), ("my_date", "string", "my_date", "string") )) ) – Vivek Goel Aug 28 '18 at 23:25

3 Answers3

2

you need to transform List[Array[String]] => List[scala.Product] in order to match input type of api you are calling.

Say, your api looks like:

scala> def glueApi(data: Seq[Product]) = "do something"
glueApi: (data: Seq[Product])String

transformation: List[Array[String]] => List[scala.Product]

scala> val data = List(Array("id", "001", "id2", "002"), Array("date1", "data1", "date2", "data2"))
data: List[Array[String]] = List(Array(id, 001, id2, 002), Array(date1, data1, date2, data2))

scala> val dataProducts:List[Product] = data.map { case Array(a, b, c, d) => (a, b, c, d) }
dataProducts: List[Product] = List((id,001,id2,002), (date1,data1,date2,data2))

call api:

scala> glueApi(dataProducts)
res3: String = do something

Note: TupleN is impl of ProductN. - https://www.scala-lang.org/api/2.12.6/scala/Tuple4.html

case class Tuple4[+T1, +T2, +T3, +T4](_1: T1, _2: T2, _3: T3, _4: T4)
  extends Product4[T1, T2, T3, T4]
{
  override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + ")"

}
prayagupa
  • 30,204
  • 14
  • 155
  • 192
1

Assuming the Arrays are each of fixed size 4 (based on your sample data), for each of the Arrays in the list, you can use pattern matching to extract the Array elements into a Tuple4:

import scala.collection.JavaConverters._
import scala.collection.mutable.ArrayBuffer

val arrList: java.util.List[Array[String]] = ArrayBuffer(
    Array("id", "string", "id", "string"),
    Array("my_date", "string", "my_date", "string")
  ).asJava
// arrList: java.util.List[Array[String]] = [[Ljava.lang.String;@1f50fe84, [Ljava.lang.String;@3380313d]

val productList: Seq[Product] = arrList.asScala.
  map{ case Array(s1, s2, s3, s4) => (s1, s2, s3, s4) }
// productList: Seq[Product] = ArrayBuffer(
//   (id,string,id,string), (my_date,string,my_date,string)
// )

Note that Tuple4 is a canonical representation of Product4, which in turn extends Product. For common conversions between Java and Scala collections, here's a relevant doc.

Leo C
  • 22,006
  • 3
  • 26
  • 39
0

You would need to convert your arrays to Tuple4s. If you can guarantee that your arrays are always of size 4, and assuming they're in the same order that the tuples require, then you could simply do this:

myList.map(arr => (arr(0), arr(1), arr(2), arr(3)))

However, if you cannot guarantee your arrays are of size 4 or if the array elements are out of order relative to the tuple requirements, then you'll have to do some extra work to deal with those cases.

Lasf
  • 2,536
  • 1
  • 16
  • 35