如何在 Scala 中更新不可变树图中的键值
How to update value of a key in a immutable tree map in Scala
我使用的是 Scala 2.11,我正在尝试更新树图中某个键的值。我尝试使用更新:
private val xyz = List(0, 100000, 500000, 1000000)
private val abc = List (0, 5, 25, 50)
private var a = TreeMap.empty[Int, TreeMap[Int, Int]] ++ xyz.map {
aa => aa -> (TreeMap.empty[Int, Int] ++ abc.map(bb => bb -> 0))
}
a(xyz(0)).foreach {
case (key, value) =>
if (key < 50) {
a(xyz(0)) = a(xyz(0)).updated(key, 5)
}
}
得到错误:
value update is not a member of scala.collection.immutable.TreeMap[Int,scala.collection.immutable.TreeMap[Int,Int]]
可以更新吗?或者有人可以帮助我使用 Java 树图复制逻辑,因为这也将允许我使用 floorEntry 和 ceilingEntry 函数。我尝试转换为 java 树状图,它生成了一个规则图,而不是树状图:
private var a = TreeMap.empty[Int, TreeMap[Int, Int]] ++ xyz.map {
aa => aa -> (TreeMap.empty[Int, Int] ++ abc.map(bb => bb -> 0)).asJava
}
private var b = a.asJava
您对 var/val
和 mutable/immutable
感到困惑。
我认为您正确理解了val
和var
之间的区别,前者是不可变变量,后者是可变变量。即,如果您尝试重新分配分配为 val
的对象,您将收到错误消息。
import scala.collection.immutable.TreeMap
val tm = TreeMap(1 -> 1, 2 -> 2, 3 -> 3)
tm = TreeMap(1->2)
^
error: reassignment to val
但是一个var
可以变异:
import scala.collection.immutable.TreeMap
var tm = TreeMap(1 -> 1, 2 -> 2, 3 -> 3)
tm = TreeMap(1->2)
// mutated tm
请注意,在后一种情况下,即使我们改变了变量,我们也没有改变集合本身,我们分配了一个新的 TreeMap
。因为我们使用 scala.collection.immutable.TreeMap
它不能被改变。
相反,如果我们使用 scala.collection.mutable.TreeMap
,它有一个 update
函数
import scala.collection.mutable.TreeMap
val tm = TreeMap(1 -> 1, 2 -> 2, 3 -> 3)
tm.update(1, 5)
tm //TreeMap(1 -> 5, 2 -> 2, 3 -> 3)
将 scala.collection.immutable.TreeMap
更改为 scala.collection.mutable.TreeMap
后,这将起作用
a(xyz(0)).foreach{ case (key, value) =>
if(key < 50){
a(xyz(0)) = a(xyz(0)).updated(key, 5) //addOne(key, 5) if 2.13+
}
}
编辑 使用 java.util.TreeMap
private val xyz = List(0, 100000, 500000, 1000000)
private val abc = List(0, 5, 25, 50)
import java.util.{TreeMap => JTreeMap}
val jTreeMap = xyz.foldLeft(new JTreeMap[Int, JTreeMap[Int, Int]]()) { (acc, elem) =>
acc.put(
elem,
abc.foldLeft(new JTreeMap[Int, Int]()) { (acc2, elem2) =>
acc2.put(elem2, 0)
acc2
}
)
acc
}
//Map created
jTreeMap.get(xyz.head).replaceAll{
//hack for scala 2.11.x
new java.util.function.BiFunction[Int, Int, Int]{
def apply(key: Int, value: Int) = if (value < 5) 5 else value
}
}
//value edited
无法更新不可变对象,您只能从旧对象创建新的不可变对象。因此,代码需要根据需要从具有不同值的原始代码创建一个新的 TreeMap
。
代码如下所示:
val newMap = a.map{
case (k, v) if k == xyz(0) =>
k -> v.map {
case (k2, v2) if k2 < 50 =>
k2 -> 5
case (k2, v2) =>
k2 -> v2
}
case (k, v) =>
k -> v
}
这分解为在外部 TreeMap
中查找匹配键的外部 map
和在内部 [=11= 中查找匹配键的内部 map
].模式匹配(case
)用于实现匹配测试,也用于提取键和值。
每个 map
都有一个 case
用于选择要修改的值,而第二种情况则保留其他值不变。第一种情况 returns 具有修改值的原始密钥,而第二种情况只是 returns 原始值 (k -> v
).
另请注意,var
适用于变量,而不是变量的内容。它指示变量是否可以更新以引用不同的对象,但没有说明变量引用的对象是否可以更新。 var
在 Scala 中很少使用,因为它违背了简洁的功能设计。
我使用的是 Scala 2.11,我正在尝试更新树图中某个键的值。我尝试使用更新:
private val xyz = List(0, 100000, 500000, 1000000)
private val abc = List (0, 5, 25, 50)
private var a = TreeMap.empty[Int, TreeMap[Int, Int]] ++ xyz.map {
aa => aa -> (TreeMap.empty[Int, Int] ++ abc.map(bb => bb -> 0))
}
a(xyz(0)).foreach {
case (key, value) =>
if (key < 50) {
a(xyz(0)) = a(xyz(0)).updated(key, 5)
}
}
得到错误:
value update is not a member of scala.collection.immutable.TreeMap[Int,scala.collection.immutable.TreeMap[Int,Int]]
可以更新吗?或者有人可以帮助我使用 Java 树图复制逻辑,因为这也将允许我使用 floorEntry 和 ceilingEntry 函数。我尝试转换为 java 树状图,它生成了一个规则图,而不是树状图:
private var a = TreeMap.empty[Int, TreeMap[Int, Int]] ++ xyz.map {
aa => aa -> (TreeMap.empty[Int, Int] ++ abc.map(bb => bb -> 0)).asJava
}
private var b = a.asJava
您对 var/val
和 mutable/immutable
感到困惑。
我认为您正确理解了val
和var
之间的区别,前者是不可变变量,后者是可变变量。即,如果您尝试重新分配分配为 val
的对象,您将收到错误消息。
import scala.collection.immutable.TreeMap
val tm = TreeMap(1 -> 1, 2 -> 2, 3 -> 3)
tm = TreeMap(1->2)
^
error: reassignment to val
但是一个var
可以变异:
import scala.collection.immutable.TreeMap
var tm = TreeMap(1 -> 1, 2 -> 2, 3 -> 3)
tm = TreeMap(1->2)
// mutated tm
请注意,在后一种情况下,即使我们改变了变量,我们也没有改变集合本身,我们分配了一个新的 TreeMap
。因为我们使用 scala.collection.immutable.TreeMap
它不能被改变。
相反,如果我们使用 scala.collection.mutable.TreeMap
,它有一个 update
函数
import scala.collection.mutable.TreeMap
val tm = TreeMap(1 -> 1, 2 -> 2, 3 -> 3)
tm.update(1, 5)
tm //TreeMap(1 -> 5, 2 -> 2, 3 -> 3)
将 scala.collection.immutable.TreeMap
更改为 scala.collection.mutable.TreeMap
后,这将起作用
a(xyz(0)).foreach{ case (key, value) =>
if(key < 50){
a(xyz(0)) = a(xyz(0)).updated(key, 5) //addOne(key, 5) if 2.13+
}
}
编辑 使用 java.util.TreeMap
private val xyz = List(0, 100000, 500000, 1000000)
private val abc = List(0, 5, 25, 50)
import java.util.{TreeMap => JTreeMap}
val jTreeMap = xyz.foldLeft(new JTreeMap[Int, JTreeMap[Int, Int]]()) { (acc, elem) =>
acc.put(
elem,
abc.foldLeft(new JTreeMap[Int, Int]()) { (acc2, elem2) =>
acc2.put(elem2, 0)
acc2
}
)
acc
}
//Map created
jTreeMap.get(xyz.head).replaceAll{
//hack for scala 2.11.x
new java.util.function.BiFunction[Int, Int, Int]{
def apply(key: Int, value: Int) = if (value < 5) 5 else value
}
}
//value edited
无法更新不可变对象,您只能从旧对象创建新的不可变对象。因此,代码需要根据需要从具有不同值的原始代码创建一个新的 TreeMap
。
代码如下所示:
val newMap = a.map{
case (k, v) if k == xyz(0) =>
k -> v.map {
case (k2, v2) if k2 < 50 =>
k2 -> 5
case (k2, v2) =>
k2 -> v2
}
case (k, v) =>
k -> v
}
这分解为在外部 TreeMap
中查找匹配键的外部 map
和在内部 [=11= 中查找匹配键的内部 map
].模式匹配(case
)用于实现匹配测试,也用于提取键和值。
每个 map
都有一个 case
用于选择要修改的值,而第二种情况则保留其他值不变。第一种情况 returns 具有修改值的原始密钥,而第二种情况只是 returns 原始值 (k -> v
).
另请注意,var
适用于变量,而不是变量的内容。它指示变量是否可以更新以引用不同的对象,但没有说明变量引用的对象是否可以更新。 var
在 Scala 中很少使用,因为它违背了简洁的功能设计。