Iva*_*van 22 collections scala map bidirectional-relation scala-collections
我想链接2列唯一标识符,并能够通过第二列值获得第一列值,并通过第一列值获得第二列值.就像是
Map(1 <-> "one", 2 <-> "two", 3 <-> "three")
Run Code Online (Sandbox Code Playgroud)
Scala有这样的设施吗?
实际上我还需要更多:3列在三元组中选择三元组中的任何一条(在整个地图中永远不会遇到单个值).但是2列双向映射也可以提供帮助.
Pet*_*itz 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
Run Code Online (Sandbox Code Playgroud)
当然可以添加语法<->而不是->.
小智 10
番石榴有一个你可以随之使用的bimap
import scala.collection.JavaConversions._
Run Code Online (Sandbox Code Playgroud)
我不认为它是开箱即用的,因为通用行为不容易提取
如何在干净的 api 中处理与多个键匹配的值?
然而,对于特定情况,这里有一个很好的练习,可能会有所帮助。它必须更新,因为没有使用哈希并且获取键或值的时间复杂度为 O(n)。
但我们的想法是让你写一些与你提议的类似的东西,但使用 Seq 而不是 Map...
在implicit和trait的帮助下,再加上find,你可以用一种干净的api(fromKey,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"))
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7514 次 |
| 最近记录: |