【问题标题】:Reading in a .csv file to scala while preserving some of the structure将 .csv 文件读入 scala,同时保留一些结构
【发布时间】:2013-09-30 09:01:16
【问题描述】:

我刚开始使用 Scala 并来自 Python。

我想读一个'|'分隔文件并保留表的结构。假设我有一个包含以下内容的文件:

1|2|3|4
5|6|7|8
9|10|11|12

我想要一个返回如下结构的函数:

List(List(1, 2, 3, 4), List(5, 6, 7, 8), List(9, 10, 11, 12))

到目前为止我的代码(由于类型不匹配而无法工作):

import scala.io.Source

def CSVReader(absPath:String, delimiter:String): List[List[Any]] = {
    println("Now reading... " + absPath)
    val MasterList = Source.fromFile(absPath).getLines().toList
    return MasterList
}

var ALHCorpus = "//Users//grant//devel//Scala-codes//ALHCorpusList"
var delimiter = "|"

var CSVContents = CSVReader(ALHCorpus, delimiter)

【问题讨论】:

    标签: scala csv


    【解决方案1】:

    首先,我会尝试通过不指定返回类型来推断类型。一旦你得到正确的结果,然后开始限制返回类型并相应地调整 CSVContents 返回的内容。这将修复类型错误。

    def CSVReader(absPath:String, delimiter:String) = { ...}
    

    CSVContents 然后返回:

    scala> CSVContents
    res0: List[String] = List(1|2|3|4, 5|6|7|8, 9|10|11|12)
    

    res0List[List[Any]] 的一种方法是使用正则表达式贪婪地提取数字。在 Scala 中,正则表达式就是 "\\d+".r

    val digitRegex = "\\d+".r
    var CSVContents = CSVReader(ALHCorpus, delimiter).map(x => digitRegex.findAllIn(x).toList) 
    

    现在CSVContents 变成了这样:

    CSVContents: List[List[String]] = List(List(1, 2, 3, 4), List(5, 6, 7, 8), List(9, 10, 11, 12))
    

    【讨论】:

    • 感谢您的回复,但主要问题不在于如何(或是否)正确设置返回值的类型。主要问题是如何执行必要的“字符串和类型体操”以获得我想要的形式。
    • @GrantD71 我已经使用正则表达式更新了答案,我认为这比我在初始答案中所说的过滤和映射更简单。
    • 我并不是要指定一个只有整数的用例。我的实际问题是包含许多不同类型数据的列。
    • @GrantD71 使其适用于每列中的不同类型需要更多的工作。假设您在列中有StringIntDouble 类型,那么您必须使用适当的正则表达式解析每一列。在 Scala 中,这可以使用 RegexParsers 解析器组合器并为每种类型定义一个解析器来完成。然后构造一个Parser 以在每一列解析其中一种类型。即使这样,生成的List 的类型也会是Any。见stackoverflow.com/questions/5063022/…
    【解决方案2】:

    对于这类事情,我只会使用 CSV 库。当我不得不做类似的事情时,我使用了scala-csv

    如果你不想这样做,你不能简单地用你的分隔符分割吗?即,

    import scala.io.Source
    
    def CSVReader(absPath:String, delimiter:String): List[List[Any]] = {
        println("Now reading... " + absPath)
        val MasterList = Source.fromFile(absPath).getLines().toList map {
            // String#split() takes a regex, thus escaping.
            _.split("""\""" + delimiter).toList
        }
        return MasterList
    }
    
    var ALHCorpus = "//Users//grant//devel//Scala-codes//ALHCorpusList"
    var delimiter = "|" // I changed your delimiter to pipe since that's what's in your sample data.
    
    var CSVContents = CSVReader(ALHCorpus, delimiter)
    

    【讨论】:

      【解决方案3】:

      假设一个 Seq 的元组是可以接受的(看看你的 cmets 这可能是你想要的)你可以用product-collections 做到这一点。 product-collections 内部使用 opencsv。

       scala> CsvParser[Int,Int,Int,Int].parseFile("x", delimiter="|")
       res2: org.catch22.collections.immutable.CollSeq4[Int,Int,Int,Int] = 
       CollSeq((1,2,3,4),
               (5,6,7,8),
               (9,10,11,12))
      

      【讨论】:

        猜你喜欢
        • 2013-12-11
        • 1970-01-01
        • 2013-12-16
        • 2018-07-18
        • 1970-01-01
        • 2016-01-26
        • 1970-01-01
        • 2019-01-31
        • 1970-01-01
        相关资源
        最近更新 更多