Drain two HashMaps in Scala

I need to create

def MergeWith[Id, X, Y, Z](x: HashMap[Id, X], y: HashMap[Id, Y], f: (X, Y) => Z): HashMap[Id, Z]

I want to:

1) iterations over x

2) for the keys that are represented in y, give f(x[key], y[key])as a result:HashMap[Id, Z]

For everything that I come up with, I get compilation errors. I do not understand how to fight.

For instance,

def andWith[K, X, Y, Z] (x: HashMap[K, X], y: HashMap[K, Y], f: (X, Y) => Z): HashMap[K, Z] = {
  for {
    (x_name, x_value) <- x
    if y.contains(x_name)
  } yield x_name -> f(x_value, y.get(x_name))
}

produces

Error:(14, 39) type mismatch;
 found   : Option[Y]
 required: Y
 } yield x_name -> f(x_value, y.get(x_name))
                              ^

which is predictable, but I can’t deploy the option.

+4
source share
1 answer

Below is a very concise and reasonably idiomatic way of writing this in Scala:

def mergeWith[K, X, Y, Z](xs: Map[K, X], ys: Map[K, Y])
  (f: (X, Y) => Z): Map[K, Z] =
    xs.flatMap {
      case (k, x) => ys.get(k).map(k -> f(x, _))
    }

Please note that I use Mapinstead HashMapand slightly changed some identifier names. I also included a function in my own parameter list, which can make the syntax a bit cleaner for the user.

, , . - (k, v) xs ys.get(k), Option[Y], Some[Y], ys None . Map Option, Y ( ) (K, Z).

, ys.get(k).map(k -> f(x, _)) Option[(K, Z)], . Map xs, Seq[Option[(K, Z)]], flatMap, Map[K, Z], ( , .

:

scala> val mapX = Map('a -> 1, 'b -> 2)
mapX: scala.collection.immutable.Map[Symbol,Int] = Map('a -> 1, 'b -> 2)

scala> val mapY = Map('b -> "foo", 'c -> "bar")
mapY: scala.collection.immutable.Map[Symbol,String] = Map('b -> foo, 'c -> bar)

scala> mergeWith(mapX, mapY) { (x, y) => (x, y) }
res0: Map[Symbol,(Int, String)] = Map('b -> (2,foo))

, .

+6

All Articles