Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何读取CSV文件并将其内容放入Scala中的地图中?_Scala_Csv_Map - Fatal编程技术网

如何读取CSV文件并将其内容放入Scala中的地图中?

如何读取CSV文件并将其内容放入Scala中的地图中?,scala,csv,map,Scala,Csv,Map,我有一个CSV文件,其中包含一个数据矩阵。此矩阵的第一列包含标签,其他列包含与标签(即第一列)关联的值。现在我想读取这个CSV文件,并将数据放入Scala中的Map[String,Array[String]]中。映射的键应该是标签(在第一列中),映射值应该是其他值(在其余列中)。要读取CSV文件,我使用opencsv val isr: InputStreamReader = new InputStreamReader(getClass.getResourceAsStream("test.csv"

我有一个CSV文件,其中包含一个数据矩阵。此矩阵的第一列包含标签,其他列包含与标签(即第一列)关联的值。现在我想读取这个CSV文件,并将数据放入Scala中的Map[String,Array[String]]中。映射的键应该是标签(在第一列中),映射值应该是其他值(在其余列中)。要读取CSV文件,我使用opencsv

val isr: InputStreamReader = new InputStreamReader(getClass.getResourceAsStream("test.csv"))`  
val data: IndexedSeq[Array[String]] = new CSVReader(isr).readAll.asScala.toIndexedSeq`
现在,我在一个
IndexedSeq[Array[String]]
中有了所有数据。我可以在这里使用这种函数式方法吗?或者我最好选择一种迭代方法,因为一次读取所有数据可能会变得复杂?现在我需要从这个IndexedSeq创建贴图。因此,我将IndexedSeq映射到
Tupel[String,Array[String]]
的IndexedSeq,以将标签值与其余值分开,然后从中创建映射

val result: Map[String, Array(String) = data.filter(e => !e.isEmpty).map(e => (e.head,e.tail)).toMap
这适用于小示例,但当我使用它读取CSV文件的内容时,它会抛出java.lang.RuntimeException。我还尝试使用groupBy创建地图,或者创建多个地图(每行一个),然后将它们缩小为一个大地图,但没有成功。我还读了另一篇关于stackoverflow的文章,有人认为toMap的复杂性为O(n²)。我在StackTrace的末尾得到了这个(整个StackTrace相当长)


有人知道从CSV文件中的数据创建映射的另一种方法吗?

您可以跳过tuple的中间
列表
,直接像这样构建映射:

val result: Map[String, Array[String]] = data.filter(e => !e.isEmpty).map(e => (e.head,e.tail))(collection.breakOut)
虽然不确定这是否能解决您的问题,但您确实询问了是否有其他方法来构建地图。您可以在此处阅读有关集合的更多信息

这对我很有效:

import scala.io.Source
Source.fromFile("some_very_big_file").getLines.map(_.split(";")).count(_ => true)
split
将CSV文件的每一行分解为简单记录。
计数
仅用于检查文件是否已真正读取

所以现在我们可以用它来读取一个真正的CSV文件(尽管我只测试了一个小文件):


这对于简单的CSV文件非常有效。如果你有更复杂的(例如,条目分散在几行上),你可能需要使用更复杂的CSV解析器(例如,但通常这样的解析器也会给你某种迭代器,你可以在上面使用相同的
映射(…zip…
函数)。

不完全是你想要的,但下面是如何使用我自己的狗食:

val data = CsvParser[String,Int,Double].parseFile("sample.csv")
data: org.catch22.collections.immutable.CollSeq3[String,Int,Double] = 
CollSeq((Jan,10,22.33),
        (Feb,20,44.2),
        (Mar,25,55.1))

scala> val lookup=(data._1 zip data).toMap
lookup: scala.collection.immutable.Map[String,Product3[String,Int,Double]] = Map(Jan -> (Jan,10,22.33), Feb -> (Feb,20,44.2), Mar -> (Mar,25,55.1))

scala> lookup("Feb")
res0: Product3[String,Int,Double] = (Feb,20,44.2)

你能说哪一个
java.lang.RuntimeException
被准确抛出吗?(我的意思是可能有一条消息,或者如果没有,你能提供堆栈跟踪吗?)我添加了一些stacktrace。我希望这会有所帮助。谢谢。这似乎是一个与specs2相关的问题,您能否也包括您的spec代码。我猜您正在测试spec的构造函数中进行此映射构建,但由于某种原因失败并停止创建spec。此外,请在specs2测试之外尝试此代码我不确定我是否理解你的意思。我基本上做的是我有一个类,它在构造函数中有CSV读取和映射创建。该类的一些方法使用此映射然后计算特定值。使用Spec类,我测试ght值是计算出来的。因此,我在规范中创建了一个类的实例并调用了该方法。嗯……我是否应该定义一个伴生对象,因为这就像java中的一个静态类,所以csv文件只能读取一次?但我想这不是我实际问题的原因。嘿。谢谢你的回答,但我已经尝试过breakout(对不起,我忘了提到它),它也不起作用。我不太熟悉读取文件的几种方法,但是如果我的类在jar库中,这也起作用吗?我想我需要以流的形式读取文件,但不确定。如果你的CSV在jar库中,你可以使用class.getResourceAsStream(而不是Source.fromFile)来获取InputStream。其余的工作方式如上所述。
scala> val content=Source.fromFile("test.csv").getLines.map(_.split(";"))
content: Iterator[Array[java.lang.String]] = non-empty iterator

scala> val header=content.next
header: Array[java.lang.String] = Array(Elements, Duration)

scala> content.map(header.zip(_).toMap)
res40: Iterator[scala.collection.immutable.Map[java.lang.String,java.lang.String]] = non-empty iterator
val data = CsvParser[String,Int,Double].parseFile("sample.csv")
data: org.catch22.collections.immutable.CollSeq3[String,Int,Double] = 
CollSeq((Jan,10,22.33),
        (Feb,20,44.2),
        (Mar,25,55.1))

scala> val lookup=(data._1 zip data).toMap
lookup: scala.collection.immutable.Map[String,Product3[String,Int,Double]] = Map(Jan -> (Jan,10,22.33), Feb -> (Feb,20,44.2), Mar -> (Mar,25,55.1))

scala> lookup("Feb")
res0: Product3[String,Int,Double] = (Feb,20,44.2)