Scalaマップのキーと値の両方をマップする


89

ScalaのMapLike特性にはメソッドがあります

mapValues [C] (f: (B) ⇒ C): Map[A, C] 

しかし、私は時々別のタイプが欲しい:

mapKeysAndValues [C] (f: (A, B) ⇒ C): Map[A, C] 

これを行う簡単な方法はありますか?もちろん、これは折り目で行うことができます。

回答:


164

mapメソッドはすべての(key, value)ペアを反復します。次のように使用できます。

val m = Map("a" -> 1, "b" -> 2)

val incM = m map {case (key, value) => (key, value + 1)}

8
すでに機能がある場合は、f : (A,B) => (A,C)簡単にできますm.map(f.tupled)。で動作しますval f = (x: String, y: Int) => (x, y+1)が、奇妙なことに、fと同等に定義すると、replは不平を言いますdef
Dan Burton

2
キーワードcaseはここで何を達成しますか?
遍在

{case (key, value) => ...}この場合、@ Omnipresent は単なるパターンマッチングです。に関数を提供する代わりにmap、部分的な関数を与えます。
tenshi 2016

注:caseパターンに型を入れることができますが、これはランタイムエラーを発生させる可能性があるため、安全ではありません(これは単なるパターンマッチであるため)。一方、map関数の下のコレクションの構造を変更して、オブジェクトとして解釈するオブジェクトが少なすぎたり多すぎたりすると(key, value)、もう一度、実行時エラーが発生するはずです。:(
コンビネータ

8

このコードはどうですか:

val m = Map(1 -> "one", 2 -> "two")
def f(k: Int, v: String) = k + "-" + v
m map {case (k, v) => (k, f(k, v))}

生成されるもの:

 Map(1 -> 1-one, 2 -> 2-two)

これはユーティリティメソッドにパッケージ化できます。

def mapKeysAndValues[A,B,C](input: Map[A,B], fun: (A, B) => C) = 
  input map {case(k,v) => (k, fun(k, v))}

使用法:

mapKeysAndValues(
  Map(1 -> "one", 2 -> "two"), 
  (k: Int, v: String) => k + "-" + v
)

これは同じMapLike#transformですか?
Hosam Aly 2017


2

いくつかのScalazで:

scala> def fst[A, B] = (x: (A, B)) => x._1
fst: [A, B]=> (A, B) => A

scala> Map(1 -> "Lorem", 2 -> "Ipsum").map(fst &&& Function.tupled(_.toString + _))
res1: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> 1Lorem, 2 -> 2Ipsum)

@tenshiのソリューションの方が好きです。


0

ユーティリティクラスを作成できます。

class MyMapLike[K,V](m:MapLike[K,V,_]){
 def mapKeysAndValues[R](f: (K, V) => R)={
   m.map{case (k,v)=> f(k,v)}
 } 
}
object MyMapLike{
 implicit def maplike2mymaplike[K,V](ml:MapLike[K,V,_]):MyMapLike[K,V]=new MyMapLike(m)

}

import MyMapLike._
Map(1 -> "one", 2 -> "two").mapKeysAndValues(k,v=>v*k)

テストされていないコードですが、そのように動作するはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.