# Set map smoothing

I'm trying to flatten a map where the keys are shared, in the sense that:

``````Map( Set(1, 2, 3) -> 'A', Set(4, 5, 6) -> 'B')
```

```

should flatten:

``````Map(5 -> B, 1 -> A, 6 -> B, 2 -> A, 3 -> A, 4 -> B)
```

```

Here's what I did:

``````def fuse[A, B, T <: Traversable[A]](mapOfTravs: Map[T, B]): Map[A, B] = {
val pairs = for {
trav <- mapOfTravs.keys
key <- trav
} yield (key, mapOfTravs(trav))
pairs.toMap
}
```

```

It works. But:

• Is there an easier way to do this?

• I don't really like Scala's type system, and I'm sure it can be improved. I have to specify types explicitly when I use my function:

``````val map2 = Map( Set(1, 2, 3) -> 'A', Set(4, 5, 6) -> 'B')
val fused2 = fuse[Int, Char, Set[Int]](map2)

val map1: Map[Traversable[Int], Char] = Map( Set(1, 2, 3) -> 'A', Set(4, 5, 6) -> 'B')
val fused1 = fuse[Int, Char, Traversable[Int]](map1)
```

```

PS: This function `fuse`

doesn't make much sense when the key intersections have a non-bubble intersection.

+3

source to share

Like @Azzie I was thinking about zip, but maybe Azzie has an edge with these zees.

``````scala> val m = Map( Set(1, 2, 3) -> 'A', Set(4, 5, 6) -> 'B')
m: scala.collection.immutable.Map[scala.collection.immutable.Set[Int],Char] = Map(Set(1, 2, 3) -> A, Set(4, 5, 6) -> B)

scala> (m map { case (k, v) => k zip (Stream continually v) }).flatten.toMap
res0: scala.collection.immutable.Map[Int,Char] = Map(5 -> B, 1 -> A, 6 -> B, 2 -> A, 3 -> A, 4 -> B)

scala> (m map { case (k, v) => k zipAll (Nil, null, v) }).flatten.toMap
res1: scala.collection.immutable.Map[Any,Char] = Map(5 -> B, 1 -> A, 6 -> B, 2 -> A, 3 -> A, 4 -> B)

scala> m flatMap { case (k, v) => k zip (Stream continually v) }
res2: scala.collection.immutable.Map[Int,Char] = Map(5 -> B, 1 -> A, 6 -> B, 2 -> A, 3 -> A, 4 -> B)
```

```

It is not clear how to generalize this well.

+2

source

This is basically what you do in an understanding, but simplified a little:

``````  def fuse[A, B, T <: Traversable[A]](mapOfTravs: Map[T, B]): Map[A, B] = {
mapOfTravs.flatMap({ case (s, c) => s.map(i => i -> c) })
}
```

```

Not much can be done by type, I'm sure there are some types of lambda chenins you can do, I'm just not sure how to implement them ...

UPDATE Here's a bit better for the version, same as above flatMap:

``````  def fuse2[A, B, T <: Traversable[A]](mapOfTravs: Map[T, B]): Map[A, B] = {
for {
(keys, value) <- mapOfTravs
key <- keys
} yield key -> value
}
```

```
+4

source

It looks terrible and using 0 is cheating, but it gets the job done

`````` m.map( {case (s,c) => s.zipAll(Set(c),0,c)} ).flatten.toMap
```

```
+1

source

Since I seem to be in a "terribly generic implication", kick lately :

``````import scala.collection.MapLike
import scala.collection.TraversableLike
import scala.collection.generic.CanBuildFrom

implicit class Map_[
A,
B,
T1 : ({type L[X] = X => TraversableLike[A, T2]})#L,
T2,
M1 : ({type L[X] = X => MapLike[T1, B, M2]})#L,
M2 <: MapLike[T1, B, M2] with Map[T1, B]
](map: M1) {

def fuse[M3](implicit cbfM: CanBuildFrom[M2, (A, B), M3]) : M3 =
map.flatMap({ case (k, v) => k.toTraversable.map((_, v)) })
}
```

```

Examples:

``````scala> Map(Set(1, 2, 3) -> 'A', Set(4, 5, 6) -> 'B').fuse
res: scala.collection.immutable.Map[Int,Char] =
Map(5 -> B, 1 -> A, 6 -> B, 2 -> A, 3 -> A, 4 -> B)

scala> Map(Array(1, 2, 3) -> 'A', Array(4, 5, 6) -> 'B').fuse
res: scala.collection.immutable.Map[Int,Char] =
Map(5 -> B, 1 -> A, 6 -> B, 2 -> A, 3 -> A, 4 -> B)
```

```
+1

source

All Articles