2017-05-27 43 views
1

我有一個文件名爲「mappings.txt」的格式:讀取文件到地圖

k->v 

要讀取這個文件放到一個地圖使用:

val file = Source.fromFile("mappings.txt").getLines.filter(f => !f.trim.isEmpty) 
val map = file.map(m2 => (m2.split("->")(0), m2.split("->")(1))).toMap 

如何讀取文件到在多行顯示值的地圖? 但一些映射值是多行:如:

k -> v \n 
     test 
     \n here 
k2 -> v2 
+0

你說的值是多行的,那麼'k'的值是多少?是'v'還是'test'或'here'? –

回答

1

這似乎對我來說,工作給予非常有限的測試數據的工作。

val myMap = io.Source 
       .fromFile("junk.txt")    // open the file 
       .mkString       // turn it into one long String 
       .split("(?=\\n\\S+\\s*->)")  // a non-consuming split 
       .map(_.trim.split("\\s*->\\s*")) // split each element at "->" 
       .map(arr => (arr(0)->arr(1)))  // from 2-element Array to tuple 
       .toMap       // from tuple to k->v pair 

結果:

scala> myMap("k") 
res0: String = 
v \n 
     test 
     \n here 

scala> myMap("k2") 
res1: String = v2 
1

下面是尾遞歸函數,將組指定的方式您的輸入線。

想法很簡單:逐行處理輸入。遇到key->value對時,將其添加到緩衝區(或累加器)。當行看起來不像k->v對時,將此行添加到已存在於緩衝區中的最後一對的值字符串中。

val s = 
    """k -> v \n 
    |  test 
    |  \n here 
    |k2 -> v2 
    """.stripMargin.split("\n").toList 


def rec(input:List[String]):Map[String, String] = { 
    val ARROW = "\\s*(.+?)\\s*->\\s*(.+?)\\s*".r 

    def r0(in:List[String], accum:List[(String, List[String])]):List[(String, List[String])] = in match { 
    // end of input, reverse line accumulators 
    case Nil => accum.map{case (k, lines) => k -> lines.reverse}.reverse 

    // key -> value line encountered, adding new k->v pair to outer accumulator 
    case ARROW(k, v) :: tail => r0(tail, (k, List(v)) :: accum) 

    // line without key encountered, adding this line to previous k->v pair in the accumulator 
    case line :: tail => r0(tail, accum match { 
     case (k, lines) :: accTail => (k, line :: lines) :: accTail 
     case _ => accum // if accum is empty and input doesn't have a key, ignore line 
    }) 
    } 

    r0(input, Nil).toMap.mapValues(_.mkString("\n")) 
} 

rec(s).foreach(println(_)) 

結果:

(k,v \n 
    test 
    \n here) 
(k2,v2 
) 

每一行被處理正好一次,也緩衝區的每個的增加和修改是O(1),所以整個過程是O(N)。

此外,請注意,您正在以保留資源的方式閱讀文件。請參閱to this for details