Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Scala, is it possible to zip two lists of differing sizes?

Tags:

scala

For example suppose I have

val letters = ('a', 'b', 'c', 'd', 'e')
val numbers = (1, 2)

Is it possible to produce a list

(('a',1), ('b',2), ('c',1),('d',2),('e',1))
like image 388
deltanovember Avatar asked Dec 24 '11 00:12

deltanovember


People also ask

What happens if you zip two lists of different lengths?

Zipping lists of unequal or different lengths results in a zip object that is as long as the shortest iterable in the items being passed in. This means, that if you pass in a list that is 5 items long, and another list that is one million items long, you'll end up with a zip item that contains five items.

How does zip work in Scala?

The zip function is applicable to both Scala's Mutable and Immutable collection data structures. The zip method takes another collection as parameter and will merge its elements with the elements of the current collection to create a new collection consisting of pairs or Tuple2 elements from both collections.

How do you find the difference between two lists in Scala?

In Scala Stack class , the diff() method is used to find the difference between the two stacks. It deletes elements that are present in one stack from the other one. Return Type: It returns a new stack which consists of elements after the difference between the two stacks.


2 Answers

Your letters and numbers are tuples, not lists. So let's fix that

scala> val letters = List('a', 'b', 'c', 'd', 'e')
letters: List[Char] = List(a, b, c, d, e)

scala> val numbers = List(1,2)                    
numbers: List[Int] = List(1, 2)

Now, if we zip them we don't get the desired result

scala> letters zip numbers
res11: List[(Char, Int)] = List((a,1), (b,2))

But that suggests that if numbers were repeated infinitely then the problem would be solved

scala> letters zip (Stream continually numbers).flatten
res12: List[(Char, Int)] = List((a,1), (b,2), (c,1), (d,2), (e,1))

Unfortunately, that's based on knowledge that numbers is shorter than letters. So to fix it all up

scala> ((Stream continually letters).flatten zip (Stream continually numbers).flatten take (letters.size max numbers.size)).toList
res13: List[(Char, Int)] = List((a,1), (b,2), (c,1), (d,2), (e,1))
like image 135
James Iry Avatar answered Nov 15 '22 21:11

James Iry


The shorter of the lists needs to be repeated indefinitely. In this case it's obvious that numbers is shorter, but in case you need it to work in general, here is how you can do it:

def zipLongest[T](list1 : List[T], list2 : List[T]) : Seq[(T, T)] =
  if (list1.size < list2.size)
    Stream.continually(list1).flatten zip list2
  else
    list1 zip Stream.continually(list2).flatten

val letters = List('a', 'b', 'c', 'd', 'e')
val numbers = List(1, 2)

println(zipLongest(letters, numbers))
like image 22
Paolo Capriotti Avatar answered Nov 15 '22 19:11

Paolo Capriotti