61

mapValuesちょうど今、それがビューを生み出すことを知って驚いています。結果を次の例に示します。

case class thing(id: Int)
val rand = new java.util.Random
val distribution = Map(thing(0) -> 0.5, thing(1) -> 0.5)
val perturbed = distribution mapValues { _ + 0.1 * rand.nextGaussian }
val sumProbs = perturbed.map{_._2}.sum
val newDistribution = perturbed mapValues { _ / sumProbs }

アイデアは、私がいくつかのランダム性で摂動されている分布を持っているということです、そしてそれを再正規化します。コードは実際には本来の意図で失敗します。mapValuesを生成するためview、が使用_ + 0.1 * rand.nextGaussianされるたびに常に再評価さperturbedれます。

私は今、distribution map { case (s, p) => (s, p + 0.1 * rand.nextGaussian) }のようなことをしていますが、それは少し冗長です。したがって、この質問の目的は次のとおりです。

  1. この事実に気づいていない人々に思い出させてください。
  2. mapValuesそれらが出力を作成する理由を探しviewます。
  3. コンクリートを製造する別の方法があるかどうかMap
  4. このトラップを持つ他の一般的に使用される収集方法はありますか?

ありがとう。

4

3 に答える 3

40

これに関するチケットがあります、SI-4776 (by YT)。

それを紹介するコミットには、次のように書かれています。

jrudolph の提案に従い、抽象マップを作成filterKeysしてmapValues 変換し、不変マップの機能を複製しました。不変のマップから一般的なマップに移動transformしました。filterNotファラーによるレビュー。

jrudolph による元の提案を見つけることができませんでしたが、mapValuesより効率的にするために行われたと思います。驚くかもしれませんが、値を複数回反復する可能性が低い場合mapValues は、より効率的です。

回避策として、mapValues(...).view.force新しいMap.

于 2013-02-14T20:10:04.923 に答える
11

Scalaのドキュメントによると:

keyこのすべてのマップをにマップするマップビューf(this(key))。結果のマップは、要素をコピーせずに元のマップをラップします。

ですから、これは予想されることですが、これは私を非常に怖がらせます。明日、たくさんのコードをレビューする必要があります。私はそのような振る舞いを期待していませんでした:-(

その他の回避策:

呼び出しtoSeqてコピーを取得できます。必要に応じてマップに戻すことがtoMapできますが、この不要なオブジェクトの作成は、使用よりもパフォーマンスに影響します。map

比較的簡単に書くことができmapValuesますが、ビューは作成されません。明日それを行い、私の前に誰もそれを行わない場合は、ここにコードを投稿します;)

編集:

ビューを「強制」する簡単な方法を見つけました。mapValuesの後に「.map(identity)」を使用します(したがって、特定の関数を実装する必要はありません)。

scala> val xs = Map("a" -> 1, "b" -> 2)
xs: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 1, b -> 2)

scala> val ys = xs.mapValues(_ + Random.nextInt).map(identity)
ys: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 1315230132, b -> 1614948101)

scala> ys
res7: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 1315230132, b -> 1614948101)

返されるタイプが実際にはビューではないのは残念です!そうでなければ、「力」と呼ぶことができたでしょう...

于 2013-02-14T19:53:33.757 に答える