将自动递增的值添加到 Scala 映射以获取空值
Add auto incremented values to scala map for null values
我有如下 Scala 映射:
val mapData = Map(AA1 -> 1, AA2 -> 2, AA3 -> null, AA4 -> null)
我想从最高地图值自动递增该值(在上面的地图中是“2”)。
val maxValue = mapData.valuesIterator.max
我想遍历此地图,如果值为 null
,则将该值替换为从最高地图值开始的自动增量值(在上面的地图中为 2
)。结果应该如下所示。顺序不重要。
Map(AA1 -> 1, AA2 -> 2, AA3 -> 3, AA4 -> 4)
我尝试使用 mapData.map()
但我无法在地图操作期间保留增加的值。 Scala 中还有其他方法可以实现吗?
首先,您提供的代码片段无法编译,因为 Null
中的值和键未在引号中交换以被视为字符串。我用 Option
:
替换了值
val mapData: Map[String, Option[Int]] = Map("AA1" -> Some(1), "AA2" -> Some(2), "AA3" -> None, "AA4" -> None)
val max = mapData.values.flatten.max
val (result, _) = mapData.toList.foldLeft(Map.empty[String, Int] -> (max + 1)) {
case ((accumulator, nextMax), (key, None)) =>
((accumulator + (key -> nextMax)), nextMax + 1)
case ((accumulator, nextMax), (key, Some(value))) =>
((accumulator + (key -> value)), nextMax)
}
println(result)
这将打印下一个结果:Map(AA1 -> 1, AA2 -> 2, AA3 -> 3, AA4 -> 4)
Scatie 示例:https://scastie.scala-lang.org/ltmhh3tuQCWf2deaLboK9w
更新:
正如@Tomer Shetah 在评论部分正确指出的那样 - max
不安全,因为 List[Int].empty.max
会抛出异常。替换为 maxOption
val mapData: Map[String, Option[Int]] = Map("AA1" -> Some(1), "AA2" -> Some(2), "AA3" -> None, "AA4" -> None)
val max = mapData.values.flatten.maxOption.getOrElse(0) //safer with maxOption
val (result, _) = mapData.toList.foldLeft(Map.empty[String, Int] -> (max + 1)) {
case ((accumulator, nextMax), (key, None)) =>
((accumulator + (key -> nextMax)), nextMax + 1)
case ((accumulator, nextMax), (key, Some(value))) =>
((accumulator + (key -> value)), nextMax)
}
println(result)
这是一种基本方法,但可能不是优化方法。
var mapData = Map("AA1" -> 1, "AA2" -> 2, "AA3" -> null, "AA4" -> null)
val nonNull = mapData.values.filter(_ != null)
val max = nonNull.map(_.toString.toInt).max
var nullCount = mapData.count(_._2==null)
mapData=mapData.map(t => {
if (t._2 == null) {
val output = (t._1, max + nullCount)
nullCount -= 1
output
}
else (t._1, t._2)
})
println(mapData)
//output : Map(AA1 -> 1, AA2 -> 2, AA3 -> 4, AA4 -> 3)
您的另一个选择是:
val startFrom = mapData.values.filter(_.isInstanceOf[Int]).map(_.asInstanceOf[Int]).maxOption.getOrElse(0) + 1
val values = LazyList.from(startFrom).iterator
val result = mapData.view.mapValues {
case x: Int => x
case null => values.next()
case _ => ???
}
请注意,result
未具体化。您需要调用 .toMap
来实现它。
代码 运行 在 Scastie
我有如下 Scala 映射:
val mapData = Map(AA1 -> 1, AA2 -> 2, AA3 -> null, AA4 -> null)
我想从最高地图值自动递增该值(在上面的地图中是“2”)。
val maxValue = mapData.valuesIterator.max
我想遍历此地图,如果值为 null
,则将该值替换为从最高地图值开始的自动增量值(在上面的地图中为 2
)。结果应该如下所示。顺序不重要。
Map(AA1 -> 1, AA2 -> 2, AA3 -> 3, AA4 -> 4)
我尝试使用 mapData.map()
但我无法在地图操作期间保留增加的值。 Scala 中还有其他方法可以实现吗?
首先,您提供的代码片段无法编译,因为 Null
中的值和键未在引号中交换以被视为字符串。我用 Option
:
val mapData: Map[String, Option[Int]] = Map("AA1" -> Some(1), "AA2" -> Some(2), "AA3" -> None, "AA4" -> None)
val max = mapData.values.flatten.max
val (result, _) = mapData.toList.foldLeft(Map.empty[String, Int] -> (max + 1)) {
case ((accumulator, nextMax), (key, None)) =>
((accumulator + (key -> nextMax)), nextMax + 1)
case ((accumulator, nextMax), (key, Some(value))) =>
((accumulator + (key -> value)), nextMax)
}
println(result)
这将打印下一个结果:Map(AA1 -> 1, AA2 -> 2, AA3 -> 3, AA4 -> 4)
Scatie 示例:https://scastie.scala-lang.org/ltmhh3tuQCWf2deaLboK9w
更新:
正如@Tomer Shetah 在评论部分正确指出的那样 - max
不安全,因为 List[Int].empty.max
会抛出异常。替换为 maxOption
val mapData: Map[String, Option[Int]] = Map("AA1" -> Some(1), "AA2" -> Some(2), "AA3" -> None, "AA4" -> None)
val max = mapData.values.flatten.maxOption.getOrElse(0) //safer with maxOption
val (result, _) = mapData.toList.foldLeft(Map.empty[String, Int] -> (max + 1)) {
case ((accumulator, nextMax), (key, None)) =>
((accumulator + (key -> nextMax)), nextMax + 1)
case ((accumulator, nextMax), (key, Some(value))) =>
((accumulator + (key -> value)), nextMax)
}
println(result)
这是一种基本方法,但可能不是优化方法。
var mapData = Map("AA1" -> 1, "AA2" -> 2, "AA3" -> null, "AA4" -> null)
val nonNull = mapData.values.filter(_ != null)
val max = nonNull.map(_.toString.toInt).max
var nullCount = mapData.count(_._2==null)
mapData=mapData.map(t => {
if (t._2 == null) {
val output = (t._1, max + nullCount)
nullCount -= 1
output
}
else (t._1, t._2)
})
println(mapData)
//output : Map(AA1 -> 1, AA2 -> 2, AA3 -> 4, AA4 -> 3)
您的另一个选择是:
val startFrom = mapData.values.filter(_.isInstanceOf[Int]).map(_.asInstanceOf[Int]).maxOption.getOrElse(0) + 1
val values = LazyList.from(startFrom).iterator
val result = mapData.view.mapValues {
case x: Int => x
case null => values.next()
case _ => ???
}
请注意,result
未具体化。您需要调用 .toMap
来实现它。
代码 运行 在 Scastie