OK、私は素晴らしいものを持っていると思います:
- 行数が異なる行列を処理します(ポスターのログファイルに行番号が異なる行列があるに違いありません:-)
- 入力全体を一度に解析するのではなく、段階的に解析します (したがって、それほど多くのメモリを使用しません)。
- 入力の検証を可能にします
準備
最初の部分は、最初の回答とほぼ同じです。しかしzipWithIndex
、入力の行番号を保持するために追加しました。
import io.Source
def rawInput = Source.fromString(
"""|3
|1 2 1
|1 2 2
|1 2 3
|4
|1 2 3 1
|1 2 3 2
|1 2 3 3
|1 2 3 4""".stripMargin) // You would probably use Source.fromFile(...)
type Matrix = List[Array[Int]]
def parsedInput = rawInput.getLines().map(_.split(" ")).map(_.map(_.toInt)).zipWithIndex
イテレータ付きバージョン
このバージョンは、変更可能な状態を持つ従来の Java イテレータを使用します。機能的なスタイルではありませんが、非常に高速に実行されるはずです。
def matrixIterator= new Iterator[Matrix] {
val input = parsedInput
var expectedNumerOfRows : Option[Int] = None
override def hasNext = input.hasNext
override def next() : Matrix = {
import collection.mutable.MutableList
var matrix : MutableList[Array[Int]] = MutableList()
while (input.hasNext) {
val (currentLine, lineNumber)=input.next()
if (currentLine.size==1){
expectedNumerOfRows=Some(currentLine.head)
return matrix.toList
}else{
matrix+=currentLine
expectedNumerOfRows.filter(_ != currentLine.size).foreach{ expected : Int =>
//println(String.format("Warning in line %s: Expected %s columns, got %s", lineNumber+1, expected, currentLine.size))
}
}
}
return matrix.toList
}
}.next()
ストリーム付きバージョン
このバージョンは Scala ストリームを使用します。再帰的 (末尾再帰的ではありません) であり、変更可能な変数は使用しません。Iterator バージョンよりも少し遅くなるはずですが、はるかに読みやすくなっています。
def matrixStream : Stream[Matrix] = {
def matrix(input : Iterator[(Array[Int], Int)], numberOfColumns : Int, currentMatrix : Matrix) : Stream[Matrix] = {
if (!input.hasNext) {
currentMatrix #:: Stream.empty
}else{
val (line, number) = input.next()
if (line.size == 1) {
currentMatrix.reverse #:: matrix(input, line.head, List.empty)
}else{
//if (numberOfColumns != line.size) println(...)
matrix(input, numberOfColumns, line :: currentMatrix)
}
}
}
matrix(parsedInput,0,List()).drop(1)
}