将自动递增的值添加到 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)

斯卡蒂:https://scastie.scala-lang.org/iiSvahIZStyL1MDi0Glsvg

这是一种基本方法,但可能不是优化方法。

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