我在Scala中建模DFA。我有一个转换矩阵,它是一个有向无环图,表示为二维矩阵(更准确地说,数组或数组)。我已经实现了一个方法getNextTransitions
,它将根据我当前的状态给出可能的下一个状态。考虑下面的两个实现,它们提供正确的输出,但使用的数据结构不同。
使用ListBuffer
:
def getNextTransitions(currState: Int): List[Edge] = {
val ret: ListBuffer[Edge] = ListBuffer[Edge]()
val row: Array[Int] = transitionDAG(currState) //row is a 1-d array
row.indices.foreach(j => {
if (row(j) != -1) {
ret += Edge(STATES(currState), STATES(j), row(j))
}
})
ret.toList
}
使用List
:
def getNextTransitions1(currState: Int): List[Edge] = {
var ret: List[Edge] = List[Edge]()
val row: Array[Int] = transitionDAG(currState) //row is a 1-d array
row.indices.foreach(j => {
if (row(j) != -1) {
ret = Edge(STATES(currState), STATES(j), row(j)) :: ret
}
})
ret
}
Scala鼓励使用不可变数据结构,但我无法在上面的var ret: List[Edge]
方法中找到用val ret: List[Edge]
替换getTransitions1
的方法。有什么建议吗?
另外,当使用getTransitions
的{{1}}方法已经完成其工作时,我是否应该尝试以另一种方式强迫自己思考?
添加ListBuffer
和State
类的定义。为简单起见,在问题中删除了类型参数。因此,Edge
类可以假定为Edge
case class Edge (start: State, end: State, edgeVal:Any)
上课:
State
case class State[+T](stateVal: T) {
override def toString: String = {
stateVal.toString
}
}
上课:
Edge
答案 0 :(得分:2)
我不确定你是否需要索引(因此zipWithIndex
):
transitionDAG(currState).zip(STATES).filter(_._1 != -1).map {
case (row, endState) => Edge(STATES(currState), endState, row)
}
只需用状态压缩行并过滤它们。
使用for-comprehension同样的事情:
for ((row, endState) <- transitionDAG(currState).zip(STATES) if row != -1)
yield Edge(STATES(currState), endState, row)
答案 1 :(得分:1)
foreach
中的indices
正在过滤row(j) != -1
Edge
,如果是,则返回新的Some
类。要模仿此过滤器,然后在此处映射行为是一种使用相同条件进行过滤并将结果包装在List[Option[Edge]]
类中的方法。如果不满足条件,则结果为None。使用此方法,我们得到flatten
。然后使用row.indices.foreach...
来获取具有值的那些案例的结果。
row.indices.map(j => if(row(j) != -1) Some(Edge(STATES(currState), STATES(j), row(j))) else None).flatten
变为
var ret: List[Edge] = List[Edge]()
这将返回一个新集合,并在Scala中返回该方法的最后一个值。甚至不需要声明 <div class="hi-icon-wrap hi-icon-effect-4 hi-icon-effect-4b">
<a href="#set-4" class="column product hi-icon product-icon"><div class="icon-text">Product</div></a>
</div>
答案 2 :(得分:1)
您可以尝试使用fold
:
def getNextTransitions1(currState: Int): List[Edge] = {
transitionDAG(currState).zipWithIndex.foldLeft(List[Edge]())({
case (ret, (row, j)) =>
if (row != -1) {
Edge(STATES(currState), STATES(j), row) :: ret
} else {
ret
}
})
}
答案 3 :(得分:1)
我提出了另一个类似于Aivean's answer的变体,它使用Scala集合上的collect
方法
Range(Cells(2, "A"), Cells(i-1, "C")).Copy
Sheets("1m").Select
Cells(2, "A").PasteSpecial xlPasteAll