假设我有这样的RDD - > (String,Date,Int)
[("sam", 02-25-2016, 2), ("sam",02-14-2016, 4), ("pam",03-16-2016, 1), ("pam",02-16-2016, 5)]
我希望将其转换为这样的列表 - >
[("sam", 02-14-2016, 4), ("pam",02-16-2016, 5)]
其中value是记录,其中每个键的日期为分钟。 这样做的最佳方式是什么?
答案 0 :(得分:4)
我认为,由于您将问题标记为与spark相关,因此您指的是RDD而不是列表。
将记录转换为2元组,使用键作为第一个元素将允许您使用reduceByKey方法,如下所示:
rdd
.map(t => (t._1, (t._2, t._3))
.reduceByKey((a, b) => if (a._1 < b._1) a else b)
.map(t => (t._1, t._2._1, t._2._2))
或者,为清晰起见使用模式匹配: (我总是发现元组的_ *访问器有点让人难以理解)
rdd
.map {case (name, date, value) => (name, (date, value))}
.reduceByKey((a, b) => (a, b) match {
case ((aDate, aVal), (bDate, bVal)) =>
if (aDate < bDate) a else b
})
.map {case (name, (date, value)) => (name, date, value)}
将a._1 < b._1
替换为适合您正在使用的日期类型的任何比较。
请参阅http://spark.apache.org/docs/latest/programming-guide.html#working-with-key-value-pairs以获取有关reduceByKey的文档,以及您可以使用spark中的键/值对执行的其他操作
如果您实际上希望使用普通的旧scala List执行此操作,则以下操作可以:
list
.groupBy(_._1)
.mapValues(l => l.reduce((a, b) => if(a._2 < b._2) a else b))
.values
.toList
为清晰起见,模式再次匹配版本:
list
.groupBy {case (name, date, value) => name}
.mapValues(l => l.reduce((a, b) => (a,b) match {
case ((aName, aDate, aValue), (bName, bDate, bValue)) =>
if(aDate < bDate) a else b
}))
.values
.toList