带有scala的textfile

时间:2018-04-21 21:20:57

标签: scala

我正在学习scala,我想执行以下任务: 我有以下文本文件作为输入:

10 location String
10 age      String
10 Salary   String 
15 job      String
10 Name     String
15 Status   String

我应该写的代码可以描述如下: 如果一行以15开头,则第二个字段必须替换为以10开头的第一个前一行的第二个字段。 因此输出应如下所示:

10 location String
10 age      String
10 Salary   String 
15 Salray   String
10 Name     String
15 Name     String

2 个答案:

答案 0 :(得分:0)

def replace1510 (lines: List[String], last10: String) : List [String] =
  if (lines.isEmpty) Nil else {
  val row = lines.head.split ("[ \t]+")
  row(0).toInt match {
    case 10 => lines.head :: replace1510 (lines.tail, row(1))
    case 15 => (row(0) + " " + last10 + "\t" + row (2)) :: replace1510 (lines.tail, last10)
    case _ => lines.head :: replace1510 (lines.tail, last10)
  }
}

scala> replace1510 (lines.toList, "").mkString ("\n")
res180: String =
10 location String
10 age      String
10 Salary   String
15 Salary   String
10 Name     String
15 Name String

根据您的需要,您的输出最终可能需要一些化妆品。

我将行拆分为空白和制表符,并期望第一个值可以作为Int进行解析,匹配它。

要么(10)更新last10值,要么用记忆的last10值替换中间字段,或者只是将行交给。

  • 所以开头的输入是6行的整个列表。
  • 不为空。
  • lines.head ,即“10 location String”被拆分为 row =(10)(location)(String)
  • 然后 row(0),即“10”,转换为Int并匹配;它匹配案例10
  • 返回 lines.head ,它是整行,与递归调用 replace1510(lines.tail,row(1))的结果相结合,其中lines.tail是列表的其余部分,第一行除外,row(1)是“location”。
  • 其余部分再次分割/匹配,同样导致第二行,现在从年龄开始在第3行休息。

我的数据准备:

scala> val data = """10 location String
     | 10 age      String
     | 10 Salary   String 
     | 15 job      String
     | 10 Name     String
     | 15 Status   String"""
data: String =
10 location String
10 age      String
10 Salary   String
15 job      String
10 Name     String
15 Status   String

scala> val lines = data.split ("\n")
lines: Array[String] = Array(10 location String, 10 age      String, "10 Salary   String ", 15 job      String, 10 Name     String, 15 Status   String)

答案 1 :(得分:0)

除了使用其他人建议的递归方法之外,另一种处理文本的方法是使用foldLeft遍历拆分子串列表来执行处理逻辑。

请注意,tuple(List [Array [String]],String)用作foldLeft的累加器,以迭代方式转换数组列表以及继承字符串元素有条件的替代。

val textArr = scala.io.Source.
  fromFile("/path/to/textfile").
  getLines.map(_.split("\\s+")).
  toList

val id1 = "10"
val id2 = "15"

val outputList = textArr.foldLeft( (List[Array[String]](), textArr.head(1)) ){
  (acc, x) => x(0) match {
    case `id1` => ( x :: acc._1, x(1) )
    case `id2` => ( x.updated(1, acc._2) :: acc._1, acc._2 )
    case _ => ( x :: acc._1, acc._2 )
  }
}._1.reverse.
map(_.mkString(" "))
// outputList: List[String] = List(10 location String, 10 age String, ...)

outputList.foreach(println)
// 10 location String
// 10 age String
// 10 Salary String
// 15 Salary String
// 10 Name String
// 15 Name String

如果您不熟悉方法foldLeft,则它具有以下签名。有关详细信息,请参阅此Scala API doc

def foldLeft[B](z: B)(op: (B, A) ⇒ B): B

[UPDATE]

如果您的输入数据是字符串列表,则可以创建textArr,如下所示,并应用上述foldLeft转换:

val stringList = Seq(
  "10 location String",
  "10 age      String",
  "10 Salary   String", 
  "15 job      String",
  "10 Name     String",
  "15 Status   String"
)

val textArr = stringList.map(_.split("\\s+"))