简体   繁体   English

Scala:使用通配符映射密钥吗?

[英]Scala: Map keys with wildcards?

Is it possible to use keys with wildcards for Scala Maps? Scala Maps是否可以使用带有通配符的键? For example tuples of the form (x,_)? 例如(x,_)形式的元组? Example: 例:

scala> val t1 = ("x","y")
scala> val t2 = ("y","x")
scala> val m = Map(t1 -> "foo", t2 -> "foo")

scala> m(("x","y"))
res5: String = foo

scala> m(("x",_))
<console>:11: error: missing parameter type for expanded function ((x$1) => scala.Tuple2("x", x$1))
              m(("x",_))
                     ^

It would be great if there was a way to retrieve all (composite_key, value) pares where only some part of composite key is defined. 如果有一种方法可以检索仅定义了复合键的一部分的所有(composite_key,值)pares,那将是很好的。 Other ways to get the same functionality in Scala? 在Scala中获得相同功能的其他方法?

使用收集怎么样

Map( 1 -> "1" -> "11", 2 -> "2" -> "22").collect { case (k@(1, _), v ) => k -> v }

In general, you can do something like 通常,您可以执行以下操作

m.filter(m => (m._1 == "x"))

but in your particular example it will still return only one result, because a Map has only one entry per key. 但在您的特定示例中,它仍然只返回一个结果,因为Map每个键只有一个条目。 If your key itself is composite then it will indeed make more sense: 如果您的密钥本身是复合密钥,那么它的确会更有意义:

scala>  Map((1,2)->"a", (1,3)->"b", (3,4)->"c").filter(m => (m._1._1 == 1))
res0: scala.collection.immutable.Map[(Int, Int),String] = Map((1,2) -> a, (1,3) -> b)

使用这样的理解:

for ( a @ ((k1,k2), v) <- m  if k1 == "x" ) yield a

Think about what is happening under the hood of the Map . 想一想Map背后发生的事情。 The default Map in Scala is scala.collection.immutable.HashMap , which stores things based on their hash codes. Scala中的默认Mapscala.collection.immutable.HashMap ,它根据哈希码存储事物。 Do ("x", "y") and ("x", "y2") have hash codes that relate to each other in anyway? ("x", "y")("x", "y2")是否具有彼此相关的哈希码? No, they don't, and their is no efficient way to implement wildcards with this map. 不,他们没有,并且这不是在此地图上实现通配符的有效方法。 The other answers provide solutions, but these will iterate over key/value pair in the entire Map , which is not efficient. 其他答案提供了解决方案,但是这些解决方案将遍历整个Map中的键/值对,效率不高。

If you expect you are going to want to do operations like this, use a TreeMap . 如果您希望进行此类操作,请使用TreeMap This doesn't use a hash table internally, put instead puts elements into a tree based on an ordering. 这在内部不使用哈希表,而是根据顺序将元素放入树中。 This is similar to the way a relational database uses B-Trees for its indices. 这类似于关系数据库将B树用于其索引的方式。 Your wildcard query is like using a two-column index to filter on the first column in the index. 通配符查询就像使用两列索引来对索引的第一列进行过滤。

Here is an example: 这是一个例子:

import scala.collection.immutable.TreeMap

val t1 = ("x","y")
val t2 = ("x","y2")
val t3 = ("y","x")
val m = TreeMap(t1 -> "foo1", t2 -> "foo2", t3 -> "foo3")

// "" is < than all other strings
// "x\u0000" is the next > string after "x"
val submap = m.from(("x", "")).to(("x\u0000", ""))

submap.values.foreach(println) // prints foo1, foo2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM