Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala permutations using two lists

Tags:

scala

What would be the best way to achieve the following please? I have two lists:

val l1 = List("a", "b") 
val l2 = List(1, 2) 

and I would like to generate this:

 List (
    List(('a', 1), ('b', 1)),
    List(('a', 1), ('b', 2)),
    List(('a', 2), ('b', 1)),
    List(('a', 2), ('b', 2))
  )  

Which is basically the first list combined with the second to create a list of list of tuples? Was thinking of using a foldLeft with a sliding(2,2) to get my results but cannot just get the right result.

The solution should work with any size and type, like List('a', 'b', 'c') and List("1", "2")

Thanks

like image 344
jts Avatar asked Nov 24 '14 09:11

jts


People also ask

How to get the list of all combinations in Scala?

Furthermore there is also a method for combinations: scala> List(1,2,3).combinations(2).mkString(" ") res4: String = List(1, 2) List(1, 3) List(2, 3) Regarding your implementation I would say three things:

How do you use multiple parameter lists in Scala?

Multiple Parameter Lists (Currying) Methods may have multiple parameter lists. Here is an example, as defined on the TraversableOnce trait in Scala’s collections API: def foldLeft[B](z: B)(op: (B, A) => B): B. foldLeft applies a two-parameter function op to an initial value z and all elements of this collection, going left to right.

How to concatenate two lists in Scala?

In order to concatenate two lists we need to utilize concat () method in Scala. In above syntax, l1 is list1 and l2 is list2. Below is the example to concat two lists in scala. Here, the identical elements are not removed.

What is list in Scala?

Scala - Lists. Scala Lists are quite similar to arrays which means, all the elements of a list have the same type but there are two important differences. First, lists are immutable, which means elements of a list cannot be changed by assignment. Second, lists represent a linked list whereas arrays are flat.


2 Answers

Trickier than I thought! The first step is to calculate the n-times Cartesian product of l2, which can be done using a combination of List.fill, combinations, and permutations (I have a hard time believing that there is no easier way to do this, but I haven't found any):

def prod[T](lst: List[T], n: Int) = List.fill(n)(lst).flatten.combinations(n).flatMap(_.permutations)

The value of n is determined by the size of list l1. In your example prod(l2, 2) will give us List(List(1, 1), List(1, 2), List(2, 1), List(2, 2)). The rest is just an application of map and zip. Together, we have

prod(l2, l1.size).map(l1.zip(_))

Output for l1 = List('a', 'b', 'c'), l2 = List("1", "2"):

List((a,1), (b,1), (c,1))
List((a,1), (b,1), (c,2))
List((a,1), (b,2), (c,1))
List((a,2), (b,1), (c,1))
List((a,1), (b,2), (c,2))
List((a,2), (b,1), (c,2))
List((a,2), (b,2), (c,1))
List((a,2), (b,2), (c,2))
like image 69
misberner Avatar answered Sep 24 '22 12:09

misberner


The best way is to use a for comprehension. Much cleaner than the accepted solution IMO :)

for {
  i1 <- List('a', 'b', 'c')
  i2 <- List(1, 2)
} yield List(i1, i2)
like image 36
lpan Avatar answered Sep 22 '22 12:09

lpan