映射这些数据的惯用方法是什么?

时间:2017-06-29 20:42:51

标签: scala

我是Scala的新手,在工作时我发现需要映射日志文件中的一些数据。日志文件遵循此格式(值从原始值更改):

1343,37284.ab1-tbd,283
1344,37284.ab1-tbd,284
1345,37284.ab1-tbd,0
1346,28374.ab1-tbd,107
1347,28374.ab1-tbd,0
...

第一个数字并不重要,但第二个字段和第三个字段的数字部分是需要映射的数字。我需要地图的键对应于第二个字段的数字部分,该数字部分映射到其后面的每个第3个字段的列表。这是一个糟糕的解释,所以这里的例子是解析上面的日志后我需要的:

{
    37284 => { 283, 284, 0 }
    28374 => { 107, 0 }
}

我想出的解决方案是:

val data = for (line <- Source fromFile "path/to/log" getLines) yield line.split(',')
val ls = data.toList

val keys = ls.map(_(1).split('.')(0).toInt)
val vals = ls.map(_(2).toInt)

val keys2vals = for {
    (k, v) <- (keys zip vals).groupBy(_._1)
    list = v.map(_._2)
} yield (k, list)

在Scala中有更惯用的方法吗?这对我来说似乎有点尴尬和困惑。 (在解释时,请假设很少或根本没有语言功能的背景知识等。)另外,如果后来我想从映射中排除数字零,我该怎么做?

编辑:

此外,我如何将数据类似地转换为表格:

{
    { 37284, { 283 ,284, 0 } }
    { 28374, { 107, 0 } }
}

即。列表[(Int,List [Int])]? (此表单用于apache-spark的索引rdds)

3 个答案:

答案 0 :(得分:0)

怎么样:

val assocList = for {
  line <- Source.fromFile("path/to/log").getLines
  Array(_, snd, thd) = line.split(',')
} yield (snd.split('.')(0).toInt, thd.toInt)
assocList.toList.groupBy(_._1).mapValues(_.map(_._2))

如果您想要List[(Int, List[Int])],请添加.toList

答案 1 :(得分:0)

我可能想用更少的线(也可以说更清晰)来写它:

${verNumber}

给出:

val l = List((1343,"37284.ab1-tbd",283),
  (1344,"37284.ab1-tbd",284),
  (1345,"37284.ab1-tbd",0),
  (1346,"28374.ab1-tbd",107),
  (1347,"28374.ab1-tbd",0))

// drop the unused data
val m = l.map(a => a._2.split('.')(0).toInt -> a._3)

// transform to Map of key -> matchedValues
m.groupBy(_._1) mapValues (_ map (_._2))

&#34;另外,如果稍后我想从映射中排除数字零,我该怎么做?&#34; - 您可以m: List[(Int, Int)] = List((37284,283), (37284,284), (37284,0), (28374,107), (28374,0)) res0: scala.collection.immutable.Map[Int,List[Int]] = Map(37284 -> List(283, 284, 0), 28374 -> List(107, 0)) 初始列表:

filter

要转换为List [(Int,List [Int])],您只需要在生成的Map上调用.toList。

答案 2 :(得分:0)

val lines = io.Source.fromFile("path/to/log").getLines.toList
lines.map{x=>
  val Array(_,second,_,fourth) = x.split("[,.]")
  (second,fourth)
}.groupBy(_._1)
.mapValues(_.map(_._2))