在Scala中加入两个CSV

时间:2017-02-15 03:31:14

标签: scala

我有两组数据。

TestScala1.txt

1,DOM,Torreto
2,Lety,贝蒂
3,鲍勃,迪伦
4,泰奥,克鲁兹
5,丹,佩雷斯
6,仁,玫瑰

TestScala2.txt

1,红,27,麦卡蒂
2,蓝色,22,帕西格
3,粉红色,25,Pateros
4,黑色,12,丽
5,Orange,20,Pasay

我尝试使用第一列通过密钥加入这两个文件。 到目前为止,这就是我目前所拥有的

import scala.collection.mutable._  
import scala.collection.immutable._  
import java.io.PrintWriter  
import scala.io.Source  

object readwritefile {
  def main(args: Array[String]){

    val id = scala.collection.mutable.Map[Int, String]()
    val fname = scala.collection.mutable.Map[Int, String]()
    val lname = scala.collection.mutable.Map[Int, String]()
    val color = scala.collection.mutable.Map[Int, String]()
    val age = scala.collection.mutable.Map[Int, String]()
    val city = scala.collection.mutable.Map[Int, String]()

    val textFromFile1 = Source.fromFile("testScala1.txt", "UTF-8")
    val textFromFile2 = Source.fromFile("testScala2.txt", "UTF-8")

    // Get key from source file
    for(line <- textFromFile1.getLines) {
        val arr = line.split(",").map(_.trim)
        id(arr(0).toInt) = arr(0)
        fname(arr(0).toInt) = arr(1)
        lname(arr(0).toInt) = arr(2)
    }

    // Join to source(2)
    for(line <-textFromFile2.getLines) {
      val arr = line.split(",").map(_.trim)
      if (id.contains(arr(0).toInt))
        color(arr(0).toInt) = arr(1)
        age(arr(0).toInt) = arr(2)
        city(arr(0).toInt) = arr(2)
    }

    id.keys.toSeq.sortBy(id).foreach{ key =>
      printf(s"id: ${id(key)} name: ${fname(key)} surname:${lname(key)} color:${color(key)} age:${age(key)} city:${city(key)}\n")
    }
    textFromFile1.close()
    textFromFile2.close()
  }
}

我的问题的主要原因是两个文件的计数不相等,因此导致错误,因为scala不允许它。 即使行数不相等,有什么办法可以加入两个文件吗?

编辑:这是错误代码

Exception in thread "main" java.util.NoSuchElementException: key not found: 6
    at scala.collection.MapLike$class.default(MapLike.scala:228)
    at scala.collection.AbstractMap.default(Map.scala:59)
    at scala.collection.mutable.HashMap.apply(HashMap.scala:65)
    at readwritefile$$anonfun$main$1.apply$mcVI$sp(readwritefile.scala:37)
    at readwritefile$$anonfun$main$1.apply(readwritefile.scala:36)
    at readwritefile$$anonfun$main$1.apply(readwritefile.scala:36)
    at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
    at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
    at readwritefile$.main(readwritefile.scala:36)
    at readwritefile.main(readwritefile.scala)

我的脚本所做的是将所有col(0)键存储到id。由于testScala2.txt没有id#6,我认为这是导致问题的原因 可能的主要目标是将两个文件连接到单个输出。

2 个答案:

答案 0 :(得分:1)

如何在集合中使用Scala的groupBy方法更简单的方法来创建相关行的cogroup?然后,您可以遍历这些组并执行任何操作。在下面的代码中,我只是打印它们:

val lines = for ((filename, idx) <- Array("TestScala1.txt", "TestScala2.txt").zipWithIndex) yield {
  Source.fromFile(filename).getLines.toArray.map { e =>
    val splits = e.split(",").toList
    (idx, splits)
  }
}
lines.flatten.groupBy(e => e._2(0)).foreach(e => println(e._1 + " = " + e._2.toList))

示例输出:

Group 4 = List((0,List(4, Taio, Cruz)), (1,List(4, Black, 12, Laguna)))
Group 5 = List((0,List(5, Dan, Perez)), (1,List(5, Orange, 20, Pasay)))
Group 6 = List((0,List(6, Jen, Rose)))
Group 1 = List((0,List(1, Dom, Torreto)), (1,List(1, Red, 27, Makati)))
Group 2 = List((0,List(2, Lety, Betty)), (1,List(2, Blue, 22, Pasig)))
Group 3 = List((0,List(3, Bob, Dylan)), (1,List(3, Pink, 25, Pateros)))

答案 1 :(得分:0)

  

我的问题是这两个文件的计数不相等,因此scala不允许它会导致错误

你不会在这里发布任何错误信息,所以我猜你的代码在执行print语句时会爆炸,对吧?这是因为如果您只是尝试根据键获取值(例如color(key)),并且如果键不存在,那么它将抛出NoSuchElementException。由于预计某些密钥可能会丢失(因为这两个文件的行数不同),您应该使用getOrElse(),例如color.getOrElse(key, "")以避免例外。

顺便说一句,您的代码在city(arr(0).toInt) = arr(2)处有一个复制/粘贴错误 - 应该是city(arr(0).toInt) = arr(3)