在scala中,如何通过给定的键从映射中获取最接近的值?
例如,我有一个在scala中,如何通过给定的键从映射中获取最接近的值?,scala,dictionary,Scala,Dictionary,例如,我有一个映射[Integer,String]像 val map = Map(1 -> "a", 2 -> "b", 3 -> "c", 5 -> "d", 9 -> "e", 100 -> "z") 如果给定的键为2,则“b”将返回 如果给定的键为50,则“e”和“z”将返回 如果给定的键为0,则“a”应返回 换句话说,如果映射中存在该键,则应返回相应的值。否则,应返回最近的较小和较大键的值(如果没有其他键较小,则应仅返回最近的较大键的值,反之亦然
映射[Integer,String]
像
val map = Map(1 -> "a", 2 -> "b", 3 -> "c", 5 -> "d", 9 -> "e", 100 -> "z")
- 如果给定的键为2,则“b”将返回
- 如果给定的键为50,则“e”和“z”将返回
- 如果给定的键为0,则“a”应返回
映射中存在该键,则应返回相应的值。否则,应返回最近的较小和较大键的值(如果没有其他键较小,则应仅返回最近的较大键的值,反之亦然)
如何做到这一点 这不是一个有效的解决方案,但您可以执行以下操作
val map =Map(1->"a",2->"b",3->"c",5->"d",9->"e",100->"z")
val keyset = map.keySet
def getNearestValues(key: Int) : Array[String] = {
if(keyset.contains(key)) Array(map(key))
else{
var array = Array.empty[String]
val less = keyset.filter(_ < key)
if(!less.isEmpty) array = array ++ Array(map(less.toList.sortWith(_ < _).last))
val greater = keyset.filter(_ > key)
if(!greater.isEmpty) array = array ++ Array(map(greater.toList.sortWith(_ < _).head))
array
}
}
val-map=map(1->“a”、2->“b”、3->“c”、5->“d”、9->“e”、100->“z”)
val keyset=map.keyset
def getNearestValues(键:Int):数组[字符串]={
if(keyset.contains(key))数组(map(key))
否则{
变量数组=数组。空[字符串]
val less=键集过滤器(u<键)
如果(!less.isEmpty)array=array++array(map(less.toList.sortWith(<\uu).last))
val更大=键集过滤器(>key)
如果(!greater.isEmpty)数组=数组++数组(映射(greater.toList.sortWith(<\uu).head))
排列
}
}
一点功能性方式
val map =Map(1->"a",2->"b",3->"c",5->"d",9->"e",100->"z")
val keyset = map.keySet
def getNearestValues(key: Int) : Array[String] = keyset.contains(key) match {
case true => Array(map(key))
case false => {
val (lower, upper) = keyset.toList.sortWith(_ < _).span(x => x < key)
val lowArray = if(lower.isEmpty) Array.empty[String] else Array(map(lower.last))
val upperArray = if(upper.isEmpty) Array.empty[String] else Array(map(upper.head))
lowArray ++ upperArray
}
}
val-map=map(1->“a”、2->“b”、3->“c”、5->“d”、9->“e”、100->“z”)
val keyset=map.keyset
def getNearestValues(key:Int):数组[String]=keyset.contains(key)匹配{
case true=>数组(映射(键))
大小写错误=>{
val(下,上)=键集.toList.sortWith(x<键)
val lowArray=if(lower.isEmpty)Array.empty[String]else数组(map(lower.last))
val upperArray=if(upper.isEmpty)Array.empty[String]else数组(map(upper.head))
lowArray++upperArray
}
}
getNearestValues(0)
应返回Array(a)
和getNearestValues(50)
应返回Array(e,z)
和getNearestValues(9)
应返回Array(e)
我建议首先将Map
转换为SortedMap
,因为需要考虑钥匙的顺序
val map = Map(1->"a",2->"b",3->"c",5->"d",9->"e",100->"z")
val sortedMap = SortedMap[Int, String]() ++ map
之后,使用以下方法获得最接近的值。结果将作为列表返回
def getClosestValue(num: Int) = {
if (sortedMap.contains(num)) {
List(sortedMap(num))
} else {
lazy val larger = sortedMap.filterKeys(_ > num)
lazy val lower = sortedMap.filterKeys(_ < num)
if (larger.isEmpty) {
List(sortedMap.last._2)
} else if (lower.isEmpty) {
List(sortedMap.head._2)
} else {
List(lower.last._2, larger.head._2)
}
}
}
将给予
List(b)
List(z, e)
List(a)
List(z)
Map
不会保留顺序,因此我建议创建一种方法:
将Map
转换为TreeMap
分别使用to(key).lastpoption
和from(key).headOption
在列表中生成上下地图条目作为选项
展平列表并提取贴图值:
示例代码如下:
val map = Map(1->"a", 2->"b", 100->"z", 9->"e", 3->"c", 5->"d")
def closestValues(m: Map[Int, String], key: Int): Seq[String] = {
import scala.collection.immutable.TreeMap
val tm = TreeMap(m.toSeq: _*)
Seq( tm.to(key).lastOption, tm.from(key).headOption ).
flatten.distinct.map{ case (k, v) => v }
}
closestValues(map, 0)
// res1: Seq[String] = List(a)
closestValues(map, 2)
// res2: Seq[String] = List(b)
closestValues(map, 50)
// res3: Seq[String] = List(e, z)
closestValues(map, 101)
// res4: Seq[String] = List(z)
更新:
从Scala2.13开始,TreeMap
的方法to
和from
分别替换为rangeTo
和rangeFrom
def getClose[K](m: Map[Int,K], k: Int): Seq[K] =
if (m.get(k).nonEmpty) Seq(m(k))
else {
val (below,above) = m.keys.partition(_ < k)
Seq( if (below.isEmpty) None else Some(below.max)
, if (above.isEmpty) None else Some(above.min)
).flatten.map(m)
}
def getClose[K](m:Map[Int,K],K:Int):Seq[K]=
if(m.get(k).非空)Seq(m(k))
否则{
val(上下)=m.keys.partition(uk
您可以解决这个问题,其复杂性比上述任何建议的解决方案都要小。因此,如果性能至关重要,请检查。另一个Scala解决方案
val m = Map(1 -> "a", 2 -> "b", 3 -> "c", 5 -> "d", 9 -> "e", 100 -> "z")
List(0, 2, 50, 101).foreach { i => {
val inp = i
val (mn, mx) = if (m.get(inp).nonEmpty) (Map(inp -> m(inp)), Map(inp -> m(inp))) else m.partition(x => x._1 > inp)
(mn, mx) match {
case (x, y) if y.isEmpty => println(m(mn.keys.min))
case (x, y) if x.isEmpty => println(m(mx.keys.max))
case (x, y) if y == x => println(m(inp))
case (x, y) => println(m(mn.keys.min), m(mx.keys.max))
}
}
}
结果:
a
b
(z,e)
z
干得好。我会将distinct
移动到映射(u._2)
调用之前,以防near-bellow键和near-bellow键引用相同的值。捕捉得好。谢谢@jwvh。我已经更新了答案。
a
b
(z,e)
z