我有一个Map [String,Info]的映射,它包含可以是大写或小写的键,如下所示:
person1: PersonInfo1
person2: PersonInfo2
PERSON1: PersonInfo1
我想获取键“ person1”的值,如果什么都找不到,我将尝试使用“ PERSON1”的键,我尝试了以下代码:
val info = map.get(key) match {
case Some(personInfo) => personInfo
case None =>
map.get(key.toUpperCase()) match {
case Some(personInfo) => personInfo
case None => None
}
}
但是此返回信息作为具有Serializable的产品类型,我如何将信息作为PersonInfo类型返回? Scala中是否有一种方法可以让我通过键从地图中获取价值,而忽略键的情况?
答案 0 :(得分:4)
有一些用于排序图的比较器,这些比较器允许不敏感地从图例中获取。示例:https://scastie.scala-lang.org/PfHTh16CROag7PNrknx1sQ
val map = scala.collection.immutable.SortedMap("key1" -> 45, "Key2" -> 43, "KEY3" -> 42)(scala.math.Ordering.comparatorToOrdering(String.CASE_INSENSITIVE_ORDER))
map.get("key1") // Some(45)
map.get("key2") // Some(43)
map.get("key3") // Some(42)
map.get("key4") // None
如果在所有情况下都返回“选项”,则可以解决您的实际问题,例如:
val info = map.get(key) match {
case somePi@Some(personInfo) => somePi
case None => map.get(key.toUpperCase()) match {
case Some(personInfo) => Some(personInfo)
case None => None
}
}
请注意somePi@
=> somePi
部分用于引用表达式或Some(personInfo)
。
大概值得解释为什么,您收到此错误消息。我假设personInfo
是实现case class
和Product
的{{1}},就像Serializable
一样。它们的常见类型是None
。
答案 1 :(得分:4)
得到Product with Serializable
的原因是因为您的代码试图返回String
(如果键是好的)或Option
(即None
找不到密钥)。这两种类型不兼容。您应该决定是否要使用String
(如果找不到密钥,则可以为空字符串)或 Option
(即Some[String]
或None
)。 / p>
看看这是否适合您。它返回一个Option[String]
。
map.get(key).fold(pm.get(key.toUpperCase))(Some(_))
第一个get()
返回一个Option
。 fold()()
会解开Option
并尝试使用大写get()
值的第二个key
,或者,如果第一个get
返回一个值,则该值为重新包装在Option
中,以使类型匹配。
另一方面,如果您想返回一个String
,则可以这样做。
map.getOrElse(key, pm.getOrElse(key.toUpperCase, ""))
答案 2 :(得分:4)
您可以使用orElse
链接获取。我将为此创建一个扩展方法:
implicit class CaseInsensitiveGetMap[V] (m: Map[String,V]) {
def iget (key: String): Option[V] = m.get(key)
.orElse(m.get(key.toUpperCase())) //you can add more orElse in chain
}
然后您可以像使用它一样
map.iget("person2")
答案 3 :(得分:0)
您可以使用 find
而不是 get
,但您在执行此操作时可能需要考虑性能。
map.find(k => k._1.equalsIgnoreCase(key)) match {
case Some =>
case None =>
}