24

一意の識別子の 2 つの列をリンクし、最初の列の値を 2 番目の列の値で取得し、2 番目の列の値を最初の列の値で取得できるようにしたいと考えています。何かのようなもの

Map(1 <-> "one", 2 <-> "two", 3 <-> "three")

Scalaにそのような機能はありますか?

実際にはもっと必要です: トリプレット内の任意のものを別のトリプレット内で選択するための 3 つの列 (マップ全体で個々の値が複数回一致することはありません)。ただし、2 列の双方向マップも役立ちます。

4

6 に答える 6

11

Guava には、一緒に使用できるbimapがあります。

import scala.collection.JavaConversions._
于 2012-03-28T10:32:40.333 に答える
10

私のBiMapアプローチ:

object BiMap {
  private[BiMap] trait MethodDistinctor
  implicit object MethodDistinctor extends MethodDistinctor
}

case class BiMap[X, Y](map: Map[X, Y]) {
  def this(tuples: (X,Y)*) = this(tuples.toMap)
  private val reverseMap = map map (_.swap)
  require(map.size == reverseMap.size, "no 1 to 1 relation")
  def apply(x: X): Y = map(x)
  def apply(y: Y)(implicit d: BiMap.MethodDistinctor): X = reverseMap(y)
  val domain = map.keys
  val codomain = reverseMap.keys
}

val biMap = new BiMap(1 -> "A", 2 -> "B")
println(biMap(1)) // A
println(biMap("B")) // 2

もちろん、 の<->代わりにfor の構文を追加することもできます->

于 2012-03-24T11:55:15.030 に答える
3

これは Guava の簡単な Scala ラッパーですBiMap

import com.google.common.{collect => guava}
import scala.collection.JavaConversions._
import scala.collection.mutable
import scala.languageFeature.implicitConversions

class MutableBiMap[A, B] private (
    private val g: guava.BiMap[A, B] = new guava.HashBiMap[A, B]()) {

  def inverse: MutableBiMap[B, A] = new MutableBiMap[B, A](g.inverse)
}

object MutableBiMap {

  def empty[A, B]: MutableBiMap[A, B] = new MutableBiMap()

  implicit def toMap[A, B] (x: MutableBiMap[A, B]): mutable.Map[A,B] = x.g
}
于 2014-09-22T09:45:29.767 に答える
2

BiMap私はScalaで本当に単純なものを持っています:

  case class BiMap[A, B](elems: (A, B)*) {

    def groupBy[X, Y](pairs: Seq[(X, Y)]) = pairs groupBy {_._1} mapValues {_ map {_._2} toSet}

    val (left, right) = (groupBy(elems), groupBy(elems map {_.swap}))

    def apply(key: A) = left(key)
    def apply[C: ClassTag](key: B) = right(key)
  }

使用法:

  val biMap = BiMap(1 -> "x", 2 -> "y", 3 -> "x", 1 -> "y")
  assert(biMap(1) == Set("x", "y"))
  assert(biMap("x") == Set(1, 3))
于 2014-05-01T22:22:40.657 に答える
1

一般的な動作を抽出するのは簡単ではないため、そのままでは存在しないと思います

クリーンなAPIで複数のキーに一致する値を処理するには?

ただし、特定のケースでは、ここで役立つ可能性のある良い演習があります。ハッシュが使用されず、キーまたは値の取得が O(n) であるため、更新する必要があります。

しかし、アイデアは、あなたが提案したものに似たものを書けるようにすることですが、Map の代わりに Seq を使用しています...

fromKeyImplicit と trait に加えて find の助けを借りて、一種のクリーンな API ( 、 )で必要なものをエミュレートできますfromValue

特異性は、値がいくつかの場所に表示されることは想定されていないということです...少なくともこの実装では。

  trait BiMapEntry[K, V] {
    def key:K
    def value:V
  }

  trait Sem[K] {

    def k:K

    def <->[V](v:V):BiMapEntry[K, V] = new BiMapEntry[K,  V]() { val key = k; val value = v}
  }

  trait BiMap[K, V] {

    def fromKey(k:K):Option[V]

    def fromValue(v:V):Option[K]
  }


  object BiMap {
    implicit def fromInt(i:Int):Sem[Int] = new Sem[Int] {
      def k = i
    }

    implicit def fromSeq[K, V](s:Seq[BiMapEntry[K, V]]) = new BiMap[K, V] {
      def fromKey(k:K):Option[V] = s.find(_.key == k).map(_.value)
      def fromValue(v:V):Option[K] = s.find(_.value == v).map(_.key)
    }

  }




  object test extends App {

    import BiMap._



    val a = 1 <-> "a"

    val s = Seq(1 <-> "a", 2 <-> "b")

    println(s.fromKey(2))
    println(s.fromValue("a"))

  }
于 2012-03-24T11:16:02.140 に答える