从列表中获取与谓词匹配的子列表

| 我对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文件不包含任何嵌套的逗号或转义符。     
已邀请:
Source.getLines已经很懒了。它返回一个Iterator,它将根据需要从基础文件获取每一行。迭代器上的大多数操作也会返回迭代器,因此在以下代码中:
val iter = src.getLines.tail map {_ split \",\"}
您正确命名了值。它将是
Iterator[Array[String]]
,每个String数组都是按需生成的。 您是否遇到任何可能导致数据延迟加载的特定问题? 更新 要从此Iterator生成子列表之一,您可以:
val id7 = iter filter {_(0) == 7)
同样,这仍然是懒惰的。 或者...您可以将批次分组:
val grouped = iter.toStream groupBy {_(0)}
不幸的是,这并不完全懒惰。最后一行的第一列可能具有唯一值,因此您需要从输入中读取每个元素,以了解需要多少个细分。在REPL中,强制子流也更容易,因此您可以查看它们包含的内容:
val grouped = iter.toStream groupBy {_(0)} mapValues {_.toList}
    
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)))
因此,您要做的是将“ 10”添加到数组中的第一个元素进行分组。     
当您有大量数据时,您必须更加小心要执行的操作。 假设您的文件太大,以至于无法将其全部加载到内存中,作为交换,您愿意(被迫)在大约11倍的时间内读取该文件,以获取11个不同的子集。 首先,您应该确定需要多少个子集。让我们创建一个假装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
有时会有所帮助,将索引值从字符串转换为整数。可能还想知道您是否真的要延迟加载,因为它会强制您多次读取整个文件。但这至少是一个基本框架。     

要回复问题请先登录注册