2016-05-16 4 views
0

私はPartialFunction[String,String]Map[String,String]を持っています。 マップ値に部分関数を適用し、それが適用されたエントリを収集したいと思います。 はすなわち与えられた:タプル構造に部分関数を適用し、タプル構造を維持する

val m = Map("a"->"1", "b"->"2") 
val pf : PartialFunction[String,String] = { 
    case "1" => "11" 
} 

私は何とかpf_._2を組み合わせて、これを実行できるようにしたいと思います:

val composedPf : PartialFunction[(String,String),(String,String)] = /*someMagicalOperator(_._2,pf)*/ 
val collected : Map[String,String] = m.collect(composedPf) 
// collected should be Map("a"->"11") 

これまでのところ、私が得た最高のは、このでした:

val composedPf = new PartialFunction[(String,String),(String,String)]{ 
     override def isDefinedAt(x: (String, String)): Boolean = pf.isDefinedAt(x._2) 
     override def apply(v1: (String, String)): (String,String) = v1._1 -> pf(v1._2) 
     } 

は良い方法ですか?

m.filter(e => pf.isDefinedAt(e._2)).mapValues(pf) 

答えて

3

は魔法のオペレータであります
scala> m collect pf.second 
res0: scala.collection.immutable.Map[String,String] = Map(a -> 11) 

これは、PartialFunctionがArrow(一般化された関数)typeclass、およびsecondは、矢印のために定義された一般的な操作の1つです。

+0

これは、私がやったことをより良くする方法のように見えます。私はもっと一般的なものを探していました。それについて考えると、レンズはそのトリックをするかもしれません。 –

+0

私はまた、成功していない何かを見つけようとしました。 '(String、String)=>(String、String)'と 'String => String'のような全く異なる型の関数を作成する必要があるか、私の例がしていることです。いずれにせよ、私はそのような結合機能のシグネチャさえも恐ろしいものではない。答えは – Mifeet

+0

です。私はレンズでこれを達成するためのすてきな方法を見つけたらここで更新します。 –

0

まさにそのScalaz内の関数は、あります:second

val composedPf: PartialFunction[(String, String), (String, String)] = 
    {case (k, v) if pf.isDefinedAt(v) => (k, pf(v))} 

別のオプションは、合成機能を作成することなく、この次のとおりです。ここで

+0

pfがPartialFunction [String、Date]であってもまだ動作しますか? –

+0

@EyalFarago 「二番目」は矢印A => Bを矢印(T、A)=>(T、B)に変換する。したがって、 'PartialFunction [String、Date]'を 'PartialFunction [(T、String)、(T、Date)]'に変換します。 'collect'で' pf.second'を直接使うと、Scalaは 'T'が' String'であることを知ることができますが、もっと複雑な場合は 'T'を明示的に指定する必要があります。 'pf.second [String]' – Kolmar

関連する問題