2017-01-09 2 views
0

Я только начал работать с scala и пытаюсь привыкнуть к языку. Мне было интересно, возможно ли следующее:Scala list 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

'Список' неизменен, поэтому вам нужно построить новый список с нужными вами элементами. – Lee

+1

Попробуйте использовать «flatMap», где внутренняя функция возвращает «Список [Инструкция]» (включая исходный элемент и новые, если применимо) –

+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()) 

Однако во втором Если вы не нуждаетесь в scala :(Так что мой совет будет состоять в том, чтобы придерживаться неизменных структур данных в scala.

Смежные вопросы