我的输入文件如下。它包含每个客户的一些购买详细信息。
输入:
100,Surender,2015-01-23,PHONE,20000
100,Surender,2015-01-24,LAPTOP,25000
101,Ajay,2015-02-21,LAPTOP,40000
101,Ajay,2015-03-10,MUSIC_SYSTEM,50000
102,Vikram,2015-07-20,WATCH,60000
我的要求是我想了解每位客户的最新购买详情。
所以预期的输出是
预期OutPut:
List(101,Ajay,2015-03-10,MUSIC_SYSTEM,50000)
List(100,Surender,2015-01-24,LAPTOP,25000)
List(102,Vikram,2015-07-20,WATCH,60000)
我尝试了下面的代码,它给了我预期的输出..
但是这下面的逻辑有点类似于java。
我的Scala代码:
package pack1
import scala.io.Source
import scala.collection.mutable.ListBuffer
object LatestObj {
def main(args:Array[String])=
{
var maxDate ="0001-01-01"
var actualData:List[String] =List()
var resultData:ListBuffer[String] = ListBuffer()
val myList=Source.fromFile("D:\\Scala_inputfiles\\records.txt").getLines().toList;
val myGrped = myList.groupBy { x => x.substring(0,3) }
//println(myGrped)
for(mappedIterator <- myGrped)
{
// println(mappedIterator._2)
actualData =mappedIterator._2
maxDate=findMaxDate(actualData)
println( actualData.filter { x => x.contains(maxDate) })
}
}
def findMaxDate( mytempList:List[String]):String =
{
var maxDate ="0001-01-01"
for(m <- mytempList)
{
var transDate= m.split(",")(2)
if(transDate > maxDate)
{
maxDate =transDate
}
}
return maxDate
}
}
有人可以帮助我使用scala以更简单的方式尝试相同的方法吗?
或者上面的代码是实现该逻辑的唯一方法吗?
答案 0 :(得分:2)
这是一个使用groupBy
和reduce
的简单版本,另外还有一个方便的案例类来优雅地表示记录:
case class Record(id: Int, username: String, date: Date, product: String, cost: Double)
val dateFormat: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
val stringList = Source.fromFile("./records.txt").getLines().toList
// split by comma and parse into case class - while REMOVING bad records
val records = stringList.map(_.split(",")).collect {
case Array(id, username, date, product, cost) => Record(id.toInt, username, dateFormat.parse(date), product, cost.toDouble)
}
// group by key, and reduce each group to latest record
val result = records.groupBy(_.id).map { _._2.reduce {
(r1: Record, r2: Record) => if (r1.date.after(r2.date)) r1 else r2
}}
result.foreach(println)
// prints:
// Record(101,Ajay,Tue Mar 10 00:00:00 IST 2015,MUSIC_SYSTEM,50000.0)
// Record(100,Surender,Sat Jan 24 00:00:00 IST 2015,LAPTOP,25000.0)
// Record(102,Vikram,Mon Jul 20 00:00:00 IDT 2015,WATCH,60000.0)
请注意,此实现不会使用 mutable 变量或集合,这通常会显着简化代码,并且对于像Scala这样的函数式语言来说更加惯用。
答案 1 :(得分:1)
甚至更简单的版本,也使用巧合相同名称的案例类。但是,不会像Tzach那样删除不良记录,而是将所有内容保留为字符串。
case class Record(id: String, name: String, dateString: String, item: String, count: String)
myList.map { line =>
val Array(id, name, dateString, item, count) = line.split(",")
Record(id, name, dateString, item, count)
}
.groupBy(_.id)
.map(_._2.maxBy(_.dateString))
.toList