3

次のようなマップを作成したいと思います。

  def one = "one"
  def two = "two"
  def three = Some("three")

  Map[String, String]("one" -> one, "two" -> two, "three" -> three)

メソッド 3 は String ではなく Option を返すため、これはコンパイルされません。私はこれを次のように機能させることができます:

Map[String, String]("one" -> one, "two" -> two) ++ three.map(t => Map("three" -> t)).getOrElse(Map.empty[String, String])

これで、一部の場合にのみオプションがリストに追加されます。

しかし、もっとエレガントな方法があるはずです。(たとえば、lift-json は、JValue を構築するときにオプションを除外する方法を知っています)。

助言がありますか?(PSここで問題を単純化しました)

4

4 に答える 4

7

Map("one" -> one, "two" -> two) ++ three.map("three" -> _)も機能します。

于 2012-07-10T15:57:48.050 に答える
4

たとえば、次の 2 種類のマップがあります。

val map1 = Map("one" -> 1, "two" -> 2)
val map2 = Map("three" -> Some(3), "four" -> None)

後者を解凍できます:

map2.collect { case (k,Some(v)) => (k,v) }

マップをマージします。

map1 ++ map2.collect{ case (k,Some(v)) => (k,v) }
于 2012-07-10T16:37:53.893 に答える
2

どの値が Options でどれがそうでないかがわかっている場合はgetOrElse、メソッド呼び出しの直後に呼び出すことができます。

Map[String, String]("one" -> one, "two" -> two, "three" -> three.getOrElse("empty"))

どのメソッドがオプションを返すかわからない場合は、暗黙的な変換を使用してオプションから値を抽出するか、次の場合はデフォルト値に設定できますNone

implicit def optToStr(a : Option[String]) : String = a.getOrElse("empty")
Map[String, String]("one" -> one, "two" -> two, "three" -> three)

後でマップ上でフィルタを使用してデフォルトのキーと値のペアを削除することもできますが、これはあまりエレガントではありません (この場合、他の誰かがより良い解決策を知っている可能性があります)。

于 2012-07-10T15:59:10.980 に答える
0

クライアントに適切なインターフェイスを提供するために、 の 1 つを拡張Mapして展開を実行できます。

class MyMap[A, B](private val tuples: (A, Option[B])*)
    extends collection.DefaultMap[A, B] {

  private val container =
    new collection.mutable.HashMap[A, B]()

  container ++= tuples collect {case (k, Some(v)) => (k, v)}

  def iterator = container.iterator
  def get(id: A) = container.get(id)
  override def size = container.size
}

(A, B)これを、ペアをペアに変換する暗黙的なものと組み合わせます(A, Option[B])

implicit def pairToPairWithSomeValue[A, B](t: (A, B)): (A, Option[B]) =
  (t._1, Some(t._2))

そしてそれを次のように使用します:

def one = "one"
def two = "two"
def three = Some("three")
def four = None


val mm = new MyMap("one" -> one, "two" -> two, "three" -> three,
                   "four" -> four)

mm foreach println
  /* (two,two), (one,one), (three,three) */
于 2012-07-10T19:13:37.000 に答える