2017-12-05 7 views
1
このコード

はScalaの

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

を持つ

に2のLinkedHashMapをマージし、それが私にこの与える:

val map1 = LinkedHashMap(4 -> (4), 7 -> (4,7)) 
val map2 = LinkedHashMap(3 -> (3), 6 -> (3,6), 7 -> (3,7)) 

val merged = mergeWith(map1,map2){ (x, y) => (x, y) } 
merged: scala.collection.mutable.LinkedHashMap[Int,(Any, Any)] = Map(7 -> ((4,7),(3,7))) 

をしかし私が欲しいのはこれです:

merged: scala.collection.mutable.LinkedHashMap[Int,(Any, Any)] = Map(3 -> (3), 4 -> (4), 6 -> (3,6), 7 -> ((4,7),(3,7))) 

コードを変更して取得するにはどうすればよいですか?

答えて

1

現在のmergeWith()署名では実行できません。特に、LinkedHashMap[K,Z]を作成しようとしていますが、Z入力はありません。 Zを取得する唯一の方法は、f()を呼び出すことです。これには、受け渡しパラメータとしてXYの両方が必要です。

xsLinkedHashMap[Int,Char]を入力し、要素(2 -> 'w')を持ち、そしてysLinkedHashMap[Int,Long]を入力し、要素(8 -> 4L)を持っているであれば、どのようにあなたは両方のキー28ため[K,Z]エントリを持つようにf(c:Char, l:Long)を起動しようとしていますか?ありえない。

mergeWith()の署名を簡略化できる場合は、次のようなことがあります。

def mergeWith[K,V](xs: collection.mutable.LinkedHashMap[K, V] 
        ,ys: collection.mutable.LinkedHashMap[K, V] 
       )(f: (V, V) => V): collection.mutable.LinkedHashMap[K,V] = { 
    val ns = collection.mutable.LinkedHashMap[K,V]() 
    (xs.keySet ++ ys.keySet).foreach{ k => 
    if (!xs.isDefinedAt(k)) ns.update(k, ys(k)) 
    else if (!ys.isDefinedAt(k)) ns.update(k, xs(k)) 
    else ns.update(k, f(xs(k), ys(k))) 
    } 
    ns 
} 

これは、あなたが与えてくれた例えば望ましい結果を生成しますが、それは変更可能なデータ構造である少なくともそのうちの望ましくない資質の数ではなく、を持っています。

ところで、Tuple1のようなものはありませんので、(4)4と同じものです。タイプAnyが表示されるたびに、デザインが再考する必要があることを示す良い兆候です。