Is there any analog for Scala 'zip' function in Groovy? - scala

In Scala I can write something like this:
val a = List(1, 2, 3)
val b = List(4, 5)
println(a zip b)
That would produce List((1,4), (2,5)) as output.
Now I have two collections in Groovy and want to zip them in similar fashion. What is the simplest way to do this?

Groovy's equivalent of Scala's zip is List#transpose, which can be called on a list of lists:
assert [[1, 2, 3], [4, 5]].transpose() == [[1, 4], [2, 5]]

Related

Adding lists by element in pyspark

I'd like to take a RDD of integer lists and reduce it down to one list. For example...
[1, 2, 3, 4]
[2, 3, 4, 5]
to
[3, 5, 7, 9]
I can do this in python using the zip function but not sure how to replicate it in spark besides doing collect on the object but I want to keep the data in the rdd.
If all elements in rdd are of the same length, you can use reduce with zip:
rdd = sc.parallelize([[1,2,3,4],[2,3,4,5]])
rdd.reduce(lambda x, y: [i+j for i, j in zip(x, y)])
# [3, 5, 7, 9]

How to pick up how to get elements from List in Scala?

I have a list of elements List(1,2,3,4,5,6) which I hope to get a few elements from it to form a new List to List(2,4,5,6).
How should I go about it? Thanks!
scala collections can be mapped or filtered. In your case you simply can filter with the function you want.
eg. in scala REPL.
filter elements which are greater than or equals to 2.
scala> List(1,2,3,4,5,6).filter(_>=2)
res3: List[Int] = List(2, 3, 4, 5, 6)
or to filter all elements which are not 1 and 3,
scala> List(1,2,3,4,5,6).filter(element => (element!=1 && element!=3))
res6: List[Int] = List(2, 4, 5, 6)
Also read
https://twitter.github.io/scala_school/collections.html#filter
http://alvinalexander.com/scala/how-to-use-filter-method-scala-collections-cookbook

Scala collection select elements until first one meet a requirement

For example I have following Scala list, I want get a sublist until there is a requirement can be met.
val list = Seq(1,2,3,4,5,5,4,1,2,5)
The requirement is the number is 5, so I want the result as:
Seq(1,2,3,4)
Currently I use Scala collection's indexWhere and splitAt to return:
list.splitAt(list.indexWhere(x => x == 5))
(Seq(1,2,3,4), Seq(5,5,4,1,2,5))
I am not sure there are more better ways to achieve the same with better Scala collection's method I didn't realise?
You can use takeWhile:
scala> val list = Seq(1,2,3,4,5,5,4,1,2,5)
list: Seq[Int] = List(1, 2, 3, 4, 5, 5, 4, 1, 2, 5)
scala> list.takeWhile(_ != 5)
res30: Seq[Int] = List(1, 2, 3, 4)
Use span like this,
val (l,r) = list.span(_ != 5)
which delivers
l: List(1, 2, 3, 4)
r: List(5, 5, 4, 1, 2, 5)
Alternatively, you can write
val l = list.span(_ != 5)._1
to access only the first element of the resulting tuple.
This bisects the list at the first element that does not hold the condition.

Zip two Arrays, always 3 elements of the first array then 2 elements of the second

I've manually built a method that takes 2 arrays and combines them to 1 like this:
a0,a1,a2,b0,b1,a3,a4,a5,b2,b3,a6,...
So I always take 3 elements of the first array, then 2 of the second one.
As I said, I built that function manually.
Now I guess I could make this a one-liner instead with the help of zip. The problem is, that zip alone is not enough as zip builds tuples like (a0, b0).
Of course I can flatMap this, but still not what I want:
val zippedArray: List[Float] = data1.zip(data2).toList.flatMap(t => List(t._1, t._2))
That way I'd get a List(a0, b0, a1, b1,...), still not what I want.
(I'd then use toArray for the list... it's more convenient to work with a List right now)
I thought about using take and drop but they return new data-structures instead of modifying the old one, so not really what I want.
As you can imagine, I'm not really into functional programming (yet). I do use it and I see huge benefits, but some things are so different to what I'm used to.
Consider grouping array a by 3, and array b by 2, namely
val a = Array(1,2,3,4,5,6)
val b = Array(11,22,33,44)
val g = (a.grouped(3) zip b.grouped(2)).toArray
Array((Array(1, 2, 3),Array(11, 22)), (Array(4, 5, 6),Array(33, 44)))
Then
g.flatMap { case (x,y) => x ++ y }
Array(1, 2, 3, 11, 22, 4, 5, 6, 33, 44)
Very similar answer to #elm but I wanted to show that you can use more lazy approach (iterator) to avoid creating temp structures:
scala> val a = List(1,2,3,4,5,6)
a: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> val b = List(11,22,33,44)
b: List[Int] = List(11, 22, 33, 44)
scala> val groupped = a.sliding(3, 3) zip b.sliding(2, 2)
groupped: Iterator[(List[Int], List[Int])] = non-empty iterator
scala> val result = groupped.flatMap { case (a, b) => a ::: b }
result: Iterator[Int] = non-empty iterator
scala> result.toList
res0: List[Int] = List(1, 2, 3, 11, 22, 4, 5, 6, 33, 44)
Note that it stays an iterator all the way until we materialize it with toList

"unlist" in scala (e.g flattening a sequence of sequences of sequences...)

Is there a simple way in Scala to flatten or "unlist" a nested sequence of sequences of sequences (etc.) of something into just a simple sequence of those things, without any nesting structure?
I don't think there is a flatten` method which converts a deeply nested into a sequence.
Its easy to write a simple recursive function to do this
def flatten(ls: List[Any]): List[Any] = ls flatMap {
case ms: List[_] => flatten(ms)
case e => List(e)
}
val a = List(List(List(1, 2, 3, 4, 5)),List(List(1, 2, 3, 4, 5)))
flatten(a)
//> res0: List[Any] = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)