我对Scala很新,但从我所看到的内容来看,它似乎是解决我正在进行的项目的理想语言。
我有一个非常大的CSV文件,如下所示:
INDEX, CITY, COST
7 , London, 500
7 , Paris, 200
11 , Rome, 300
11 , New York, 100
11 , Madrid, 7
我想读取CSV文件并生成具有相同索引的所有元素的列表,一次一个索引。
从上面的例子中我想得到一个包含行的列表:
7, London, 500
7, Paris, 200
包含行的第二个列表:
11, Rome, 300
11, New York, 100
11, Madrid, 7
在CSV文件中阅读非常简单:
val iter = src.getLines().drop(1).map(_.split(",")) //from SO :)
但是,我很难找到一种简洁的方法来生成我的子列表。在我看来,使用Scala应该有一个很好,简洁的方法来实现这一点。我特别希望数据是懒惰的,因为它有很多。你能建议我如何实现这个目标吗?
所有数据按索引排序(尽管索引不是顺序的),而我正在使用的CSV文件不包含任何嵌套的逗号或转义。
答案 0 :(得分:3)
Source.getLines已经很懒了。它返回一个Iterator,它将根据需要从底层文件中填充每一行。迭代器上的大多数操作也返回迭代器,因此在以下代码中:
val iter = src.getLines.tail map {_ split ","}
您正确命名了该值。它将是Iterator[Array[String]]
,每个String数组都是按需生成的。
您是否遇到过任何可能导致数据未被懒散加载的特定问题?
更新
然后从此迭代器生成一个子列表,您可以:
val id7 = iter filter {_(0) == 7)
同样,这仍然是懒惰的。
或者......你可以分组:
val grouped = iter.toStream groupBy {_(0)}
不幸的是,这并非完全是懒惰的。最后一行可能在第一列中具有唯一值,因此您需要从输入中读取每个元素以了解需要多少个细分。在REPL中,强制子流也更容易,因此您可以看到它们包含的内容:
val grouped = iter.toStream groupBy {_(0)} mapValues {_.toList}
答案 1 :(得分:2)
scala> List(Array(1,"a"),Array(2,"b"),Array(1,"c")).groupBy(_(0))
res1: scala.collection.immutable.Map[Any,List[Array[Any]]] = Map(1 -> List(Array(1, a), Array(1, c)), 2 -> List(Array(2, b)))
所以你要做的就是通过数组中的第一个元素将.groupBy(_(0))
添加到组中。
答案 2 :(得分:1)
当您拥有大量数据时,您必须更加小心您要执行哪些操作。
我们假设您的文件如此大,以至于您无法将其全部加载到内存中,作为交换,您愿意(强制)在〜N
中读取它时间以获得N
个不同的子集。
首先,您应该弄清楚您需要多少个子集。让我们创建一个假装getLines方法的东西:
val src = new { def getLines() = Iterator("#", "1,a", "2,b", "2,c") }
现在我们需要找到所有初始索引。你可能使用split
,但由于你正在处理大量数据并且并不真正需要它们全部细分,所以让我们找到第一个逗号(这里假设总是有一个逗号)可以找到逗号):
val idx = Set() ++ src.getLines().drop(1).map(s => s.substring(0, s.indexOf(',')))
好的,现在我们知道了我们在寻找什么。然后我们通过一个可以帮助我们延迟加载数据的类来获取它:
class OneIndex(index: String) {
lazy val data = src.getLines().drop(1).filter(
s => index == s.substring(0,s.indexOf(','))
).toArray
}
val everything = idx.map(i => (i,new OneIndex(i))).toMap
scala> everything("2").data.foreach(println)
2,b
2,c
可能会添加更多内容 - 可能.toInt
或.trim.toInt
在某些时候会有所帮助,将索引值从字符串转换为整数。人们可能也想知道你是否真的想要延迟加载,因为它会强迫你多次读取整个文件。但这至少是一个基本框架。