0

I have the following list of pairs (key,id):

val pairs =  List(('a',1), ('a',2), ('b',1), ('b',2))

I need to generate all combinations of pairs when the keys are different so the expected output is:

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

Note (List(('a',1),('a',2)) should Not be part of the output so using Scala List.combinations is not an option

I currently have the following code:

def subSeq (xs: List[(Char, Int)]): List[(Char,Int)] = {
  xs match {
    case Nil => List()
    case y::ys => {
      val eh = xs.filter (c => c._1 == y._1)
      val et = xs.filter (c => c._1 != y._1)
      for (z: (Char,Int) <- eh) yield z :: subSeq(et)
    }
  }
}

But I get an error saying List[List[(Char,Int)]] does not match List[(Char,Int)]

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
Eran Witkon
  • 4,042
  • 4
  • 19
  • 20
  • Your return type does not conform to the output you provided. If you want `List(List(), ...` as output, maybe you should return `List[List[(Char, Int)]]`?. Also a tip: you can use `list.flatten` to translate `List[List[T]]` into `List[T]` – Archeg Feb 01 '16 at 20:34
  • flatten does resolve the type mismatch but yield the wrong result - ```List((a,1), (b,1), (c,1), (b,2), (c,1), (a,2), (b,1), (c,1), (b,2), (c,1))``` which is list of pairs and not list of List of list of combinations – Eran Witkon Feb 01 '16 at 20:51

2 Answers2

0

What you are probably trying to do is this:

def subSeq (xs: List[(Char, Int)]): List[List[(Char,Int)]] = {
  xs match {
    case Nil => List(List())
    case y::ys => {
      val eh: List[(Char, Int)] = xs.filter (c => c._1 == y._1)
      val et = xs.filter (c => c._1 != y._1)
      val t = subSeq(et)
      t ++ (for {
        z: (Char,Int) <- eh
        foo <- t
      } yield z :: foo)
    }
  }
}

Your method has to return a List of Lists as that is what you are interested in. So when building up your combinations you have to iterate over the result from your recursion step.

A way using API functions would be to do it like this:

val sets = (0 to 2).flatMap{pairs.combinations}.toSet
sets.map{_.toMap}

Or this if you need the output as lists:

sets.map{_.toMap.toList}.toList

Obviously this will build more combinations than you need at first and then filter stuff out. If performance is an issue and the input does not contain any redundancies, the direct implementation is probably better.

dth
  • 2,287
  • 10
  • 17
0

eventually I used the combinations function from Scala and filtered out the non relevant matches by this filter function

def filterDup(xs: List[(Char,Int)]) : Boolean = {
    xs.map(x => x._1).size == xs.map(x => x._1).toSet.size
  }

and used it as followes:

((0 to 3).flatMap(pairs.combinations(_)) filter( filterDup(_))).toList
Eran Witkon
  • 4,042
  • 4
  • 19
  • 20