Scala:不可变的 Map 正在改变它的值
Scala: immutable Map is changing its values
我正在编写代码来确定可着色图。我正在使用 immutable Maps 来确定回溯时的顶点颜色。
在 flatMap 循环的第二次交互中,我的地图丢失了一个元素。我无法编写一个更简洁的示例来呈现相同的错误,这是我的全部代码:
import scala.collection.immutable
import scala.collection.mutable
class GraphUndirected[Vertex](vertices: Set[Vertex], edges: Set[(Vertex, Vertex)]) {
private val adjacencyList: Map[Vertex, Set[Vertex]] =
(
edges.flatMap{ case (a, b) => {Seq( (a, Set(b)), (b, Set(a)))}}
++ vertices.map((_, Set()))
)
.groupBy(_._1)
.mapValues(
_.map(_._2)
.reduce(_ ++ _)
.toSet
)
override def toString(): String = adjacencyList.toString
def kColorable[C](colors: Set[C]): Option[Map[Vertex, C]] = {
vertices.toSeq.view.flatMap( v => {
val colorsMap = immutable.Map[Vertex,C]()
kColorable[C](colors, v, colorsMap)
}).headOption
}
def kColorable[C](colors: Set[C], v: Vertex, colorMap: Map[Vertex, C]): Option[Map[Vertex, C]] = {
println(v, colorMap)
colors.toSeq.view.flatMap( c => {
if (kColorableIsSafe[C](c, v, colorMap)) {
val newColorMap = colorMap + (v -> c)
println("\tnewColorMap", newColorMap)
if (newColorMap.size == vertices.size) {
Some(newColorMap)
} else {
adjacencyList(v).toSeq.view.flatMap( u => {
println("\t\tnewColorMap", newColorMap)
if (newColorMap.contains(u)) {
None
} else {
kColorable[C](colors, u, newColorMap)
}
}).headOption
}
} else {
None
}
}).headOption
}
def kColorableIsSafe[C](c: C, v: Vertex, colorMap: Map[Vertex, C]): Boolean = {
adjacencyList(v).forall( u => {
(!colorMap.contains(u)) ||
(colorMap(u) != c)
})
}
}
val myGraph1 = new GraphUndirected[Int](
Set(1,2,3,4,5,6,7,8,9),
Set(
(1,2),
(3,2), (3,4),
(5,7), (5,9),
(6,4),
(8,2), (8,9)
)
)
println(myGraph1.kColorable[String](Set("BLACK", "WHITE")))
运行 此代码将生成:
(5,Map())
( newColorMap,Map(5 -> BLACK))
( newColorMap,Map(5 -> BLACK))
(7,Map(5 -> BLACK))
( newColorMap,Map(5 -> BLACK, 7 -> WHITE))
( newColorMap,Map(5 -> BLACK, 7 -> WHITE))
( newColorMap,Map(5 -> BLACK))
(9,Map(5 -> BLACK))
这对我来说没有意义。在第一次交互中它打印 newColorMap,Map(5 -> BLACK, 7 -> WHITE)
,但在第二次交互中“7->WHITE”消失了 newColorMap,Map(5 -> BLACK)
.
newColorMap
不应该是不可变的,不改变它的值?
我的 Scala 版本:
$ scala -version
Scala code runner version 2.12.2 -- Copyright 2002-2017, LAMP/EPFL and Lightbend, Inc.
我觉得你的代码没有错误。它 returns 预期的输出。具有欺骗性的是您选择在逐步执行程序时输出程序内部状态的方式。
要了解发生了什么,请尝试 运行 同一程序的这个版本。只需将代码复制并粘贴到 Kcolor.scala,将其放入其文件夹并输入
scalac Kcolor.scala
scala Kcolor
这里是Kcolor.scala
的内容
import scala.collection.immutable
object Kcolor extends App {
val myGraph1 = new GraphUndirected[Int](
Set(5,7,9),
Set((5,7), (5,9))
)
println(myGraph1.kColorable[String](Set("BLACK", "WHITE")))
}
class GraphUndirected[Vertex](vertices: Set[Vertex], edges: Set[(Vertex, Vertex)]) {
val adjacencyList: Map[Vertex, Set[Vertex]] =
(
edges.flatMap{ case (a, b) => {Seq( (a, Set(b)), (b, Set(a)))}}
++ vertices.map((_, Set()))
)
.groupBy(_._1)
.mapValues(
_.map(_._2)
.reduce(_ ++ _)
.toSet
)
override def toString(): String = adjacencyList.toString
def kColorable[C](colors: Set[C]): Option[Map[Vertex, C]] = {
vertices.flatMap( v => {
val colorsMap = immutable.Map[Vertex,C]()
kColorable[C](colors, v, colorsMap)
}).headOption
}
def kColorable[C](colors: Set[C], v: Vertex, colorMap: Map[Vertex, C]): Option[Map[Vertex, C]] = {
println(v, colorMap)
val res = colors.flatMap( c => {
if (kColorableIsSafe[C](c, v, colorMap)) {
val newColorMap = colorMap + (v -> c)
println("\tnewColorMap", v, c, newColorMap)
if (newColorMap.size == vertices.size) {
Some(newColorMap)
} else {
val res1 = adjacencyList(v).flatMap( u => {
println("\t\tnewColorMap", u, newColorMap)
if (newColorMap.contains(u)) {
None
} else {
kColorable[C](colors, u, newColorMap)
}
})
println(res1)
res1.headOption
}
} else {
None
}
}).headOption
println("end")
res
}
def kColorableIsSafe[C](c: C, v: Vertex, colorMap: Map[Vertex, C]): Boolean = {
adjacencyList(v).forall( u => {
(!colorMap.contains(u)) ||
(colorMap(u) != c)
})
}
}
我已经包含了输出的前几行:
(5,Map())
( newColorMap,5,BLACK,Map(5 -> BLACK))
( newColorMap,7,Map(5 -> BLACK))
(7,Map(5 -> BLACK))
( newColorMap,7,WHITE,Map(5 -> BLACK, 7 -> WHITE))
( newColorMap,5,Map(5 -> BLACK, 7 -> WHITE))
Set()
end
( newColorMap,9,Map(5 -> BLACK))
(9,Map(5 -> BLACK))
( newColorMap,9,WHITE,Map(5 -> BLACK, 9 -> WHITE))
( newColorMap,5,Map(5 -> BLACK, 9 -> WHITE))
Set()
end
程序正在做的是它到达 flatMap 的末尾而无法创建彩色地图,并且它正在输出 None。所以在
行之间
( newColorMap,5,Map(5 -> BLACK, 7 -> WHITE))
和
( newColorMap,9,Map(5 -> BLACK))
它正在到达当前flatMap的末尾并跳回外循环的下一次迭代。
你的节目很有趣。我想得很开心。感谢分享。
我正在编写代码来确定可着色图。我正在使用 immutable Maps 来确定回溯时的顶点颜色。
在 flatMap 循环的第二次交互中,我的地图丢失了一个元素。我无法编写一个更简洁的示例来呈现相同的错误,这是我的全部代码:
import scala.collection.immutable
import scala.collection.mutable
class GraphUndirected[Vertex](vertices: Set[Vertex], edges: Set[(Vertex, Vertex)]) {
private val adjacencyList: Map[Vertex, Set[Vertex]] =
(
edges.flatMap{ case (a, b) => {Seq( (a, Set(b)), (b, Set(a)))}}
++ vertices.map((_, Set()))
)
.groupBy(_._1)
.mapValues(
_.map(_._2)
.reduce(_ ++ _)
.toSet
)
override def toString(): String = adjacencyList.toString
def kColorable[C](colors: Set[C]): Option[Map[Vertex, C]] = {
vertices.toSeq.view.flatMap( v => {
val colorsMap = immutable.Map[Vertex,C]()
kColorable[C](colors, v, colorsMap)
}).headOption
}
def kColorable[C](colors: Set[C], v: Vertex, colorMap: Map[Vertex, C]): Option[Map[Vertex, C]] = {
println(v, colorMap)
colors.toSeq.view.flatMap( c => {
if (kColorableIsSafe[C](c, v, colorMap)) {
val newColorMap = colorMap + (v -> c)
println("\tnewColorMap", newColorMap)
if (newColorMap.size == vertices.size) {
Some(newColorMap)
} else {
adjacencyList(v).toSeq.view.flatMap( u => {
println("\t\tnewColorMap", newColorMap)
if (newColorMap.contains(u)) {
None
} else {
kColorable[C](colors, u, newColorMap)
}
}).headOption
}
} else {
None
}
}).headOption
}
def kColorableIsSafe[C](c: C, v: Vertex, colorMap: Map[Vertex, C]): Boolean = {
adjacencyList(v).forall( u => {
(!colorMap.contains(u)) ||
(colorMap(u) != c)
})
}
}
val myGraph1 = new GraphUndirected[Int](
Set(1,2,3,4,5,6,7,8,9),
Set(
(1,2),
(3,2), (3,4),
(5,7), (5,9),
(6,4),
(8,2), (8,9)
)
)
println(myGraph1.kColorable[String](Set("BLACK", "WHITE")))
运行 此代码将生成:
(5,Map())
( newColorMap,Map(5 -> BLACK))
( newColorMap,Map(5 -> BLACK))
(7,Map(5 -> BLACK))
( newColorMap,Map(5 -> BLACK, 7 -> WHITE))
( newColorMap,Map(5 -> BLACK, 7 -> WHITE))
( newColorMap,Map(5 -> BLACK))
(9,Map(5 -> BLACK))
这对我来说没有意义。在第一次交互中它打印 newColorMap,Map(5 -> BLACK, 7 -> WHITE)
,但在第二次交互中“7->WHITE”消失了 newColorMap,Map(5 -> BLACK)
.
newColorMap
不应该是不可变的,不改变它的值?
我的 Scala 版本:
$ scala -version
Scala code runner version 2.12.2 -- Copyright 2002-2017, LAMP/EPFL and Lightbend, Inc.
我觉得你的代码没有错误。它 returns 预期的输出。具有欺骗性的是您选择在逐步执行程序时输出程序内部状态的方式。
要了解发生了什么,请尝试 运行 同一程序的这个版本。只需将代码复制并粘贴到 Kcolor.scala,将其放入其文件夹并输入
scalac Kcolor.scala
scala Kcolor
这里是Kcolor.scala
的内容
import scala.collection.immutable
object Kcolor extends App {
val myGraph1 = new GraphUndirected[Int](
Set(5,7,9),
Set((5,7), (5,9))
)
println(myGraph1.kColorable[String](Set("BLACK", "WHITE")))
}
class GraphUndirected[Vertex](vertices: Set[Vertex], edges: Set[(Vertex, Vertex)]) {
val adjacencyList: Map[Vertex, Set[Vertex]] =
(
edges.flatMap{ case (a, b) => {Seq( (a, Set(b)), (b, Set(a)))}}
++ vertices.map((_, Set()))
)
.groupBy(_._1)
.mapValues(
_.map(_._2)
.reduce(_ ++ _)
.toSet
)
override def toString(): String = adjacencyList.toString
def kColorable[C](colors: Set[C]): Option[Map[Vertex, C]] = {
vertices.flatMap( v => {
val colorsMap = immutable.Map[Vertex,C]()
kColorable[C](colors, v, colorsMap)
}).headOption
}
def kColorable[C](colors: Set[C], v: Vertex, colorMap: Map[Vertex, C]): Option[Map[Vertex, C]] = {
println(v, colorMap)
val res = colors.flatMap( c => {
if (kColorableIsSafe[C](c, v, colorMap)) {
val newColorMap = colorMap + (v -> c)
println("\tnewColorMap", v, c, newColorMap)
if (newColorMap.size == vertices.size) {
Some(newColorMap)
} else {
val res1 = adjacencyList(v).flatMap( u => {
println("\t\tnewColorMap", u, newColorMap)
if (newColorMap.contains(u)) {
None
} else {
kColorable[C](colors, u, newColorMap)
}
})
println(res1)
res1.headOption
}
} else {
None
}
}).headOption
println("end")
res
}
def kColorableIsSafe[C](c: C, v: Vertex, colorMap: Map[Vertex, C]): Boolean = {
adjacencyList(v).forall( u => {
(!colorMap.contains(u)) ||
(colorMap(u) != c)
})
}
}
我已经包含了输出的前几行:
(5,Map())
( newColorMap,5,BLACK,Map(5 -> BLACK))
( newColorMap,7,Map(5 -> BLACK))
(7,Map(5 -> BLACK))
( newColorMap,7,WHITE,Map(5 -> BLACK, 7 -> WHITE))
( newColorMap,5,Map(5 -> BLACK, 7 -> WHITE))
Set()
end
( newColorMap,9,Map(5 -> BLACK))
(9,Map(5 -> BLACK))
( newColorMap,9,WHITE,Map(5 -> BLACK, 9 -> WHITE))
( newColorMap,5,Map(5 -> BLACK, 9 -> WHITE))
Set()
end
程序正在做的是它到达 flatMap 的末尾而无法创建彩色地图,并且它正在输出 None。所以在
行之间( newColorMap,5,Map(5 -> BLACK, 7 -> WHITE))
和
( newColorMap,9,Map(5 -> BLACK))
它正在到达当前flatMap的末尾并跳回外循环的下一次迭代。
你的节目很有趣。我想得很开心。感谢分享。