2017-01-09 142 views
0

我刚开始使用scala并试图习惯该语言。我想知道是否有以下可能:Scala列表foreach,在foreach循环中更新列表

我有一个Instruction对象的列表,我用foreach方法循环。我是否可以在我循环播放时向我的Instruction列表添加元素?下面是一个代码例子来解释什么,我想:

instructions.zipWithIndex.foreach { case (value, index) => 
     value match { 
     case WhileStmt() => { 
      ---> Here I want to add elements to the instructions list. 

     } 
     case IfStmt() => { 
       ... 
     } 
     _ => { 
       ... 
     } 
+1

'List's是不可变的,所以你需要建立你想要的元素的新名单。 – Lee

+1

尝试使用'flatMap',其中内部函数返回'List [Instruction]'(包括原始元素和新的元素,如果适用的话) –

+0

您想在哪里添加新元素?在列表的末尾?或者在你的比赛之后可能是正确的? – ponkin

回答

1

惯用的方法是这样的事情了相当复杂的迭代和更换逻辑:

@tailrec 
def idiomaticWay(list: List[Instruction], 
       acc: List[Instruction] = List.empty): List[Instruction] = 
    list match { 
    case WhileStmt() :: tail => 
     // add element to head of acc 
     idiomaticWay(tail, CherryOnTop :: acc) 
    case IfStmt() :: tail => 
     // add nothing here 
     idiomaticWay(tail, list.head :: acc) 
    case Nil => acc 
    } 

val updatedList = idiomaticWay(List(WhileStmt(), IfStmt())) 
println(updatedList) // List(IfStmt(), CherryOnTop) 

该解决方案与不可变列表工作,根据你的逻辑返回不同值的不可变列表

如果要最终破解左右(添加删除等),你可以使用Java ListIterator类,将允许你做所有的操作上面提到:在第二

def hackWay(list: util.List[Instruction]): Unit = { 

    val iterator = list.listIterator() 
    while(iterator.hasNext) { 
    iterator.next() match { 
     case WhileStmt() => 
     iterator.set(CherryOnTop) 
     case IfStmt() => // do nothing here 
    } 
    } 
} 

import collection.JavaConverters._ 

val instructions = new util.ArrayList[Instruction](List(WhileStmt(), IfStmt()).asJava) 

hackWay(instructions) 

println(instructions.asScala) // Buffer(CherryOnTop, IfStmt()) 

然而如果你不需要斯卡拉:(所以,我的建议是,以坚持不变的数据结构中阶