Scala List vs ListBuffer

时间:2015-09-21 18:35:20

标签: scala

我在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}}方法已经完成其工作时,我是否应该尝试以另一种方式强迫自己思考?

添加ListBufferState类的定义。为简单起见,在问题中删除了类型参数。因此,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

4 个答案:

答案 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