在Scala中查找每个客户的TotalSpent

时间:2016-08-19 05:49:50

标签: scala

我正在制定一个简单的要求,即找出每个客户的totalSpent。如果客户没有花费任何东西,那么我需要将TotalSpent Amount显示为0

custs.txt:

 100,Surender
 101,Raja
 102,Vijay

txns.txt:

 100,2015-01-29,20
 100,2015-01-30,18
 101,2015-01-14,30
 101,2015-01-17,20

Scala代码:

 import scala.io.Source

 case class Txns(custId: Int, txn_dateString: String,  spentAmount: Int)
 object totalamounteachcustomer {


  def main (args: Array[String])={


 val myCusts=Source.fromFile("C:\\inputfiles\\custs.txt").getLines().toList;

 val custsTxns=Source.fromFile("C:\\inputfiles\\txns.txt").getLines().toList;

val TxnsGrped =custsTxns.map { x => {
                                     val Array(custId,txn_dateString,spentAmount) = x.split(",")
                                     Txns(custId.toInt,txn_dateString,spentAmount.toInt)

                                     }
                              }.groupBy { txn => txn.custId }

        for(i <- myCusts)
        {
         val customer= i.split(",")(0).toInt
         val values =TxnsGrped.get(customer)

         val TotalSpentAmpunt = values match {

           case Some( a:List[Txns]) => a.map { x => x.spentAmount }.sum
           case None => 0

                                              }

         println(customer+" "+TotalSpentAmpunt)
        }
 }

 } 

以上代码有效..

输出:

 100 38
 101 50
 102 0

我们在scala中有简单的Join关键字吗?如果我们需要根据两个文件之间的公共密钥获取值,那么我们不能在scala中使用Join(内连接,左连接)之类的东西吗?

在这里,我使用scala集合Map并对每个客户进行迭代。

我们可以用简单的scala代码行来达到同样的要求吗?

2 个答案:

答案 0 :(得分:2)

在Scala中实现地图连接是小菜一碟:

def join[K, A, B](a: Map[K, A], b: Map[K, B]): Map[K, (A,B)] =
    for((k,va) <- a; vb <- b.get(k)) yield k -> (va, vb)

使用示例:

val customers = Map(
 100 -> "Surender",
 101 -> "Raja",
 102 -> "Vijay"
)

val purchases = Seq(
 (100,"2015-01-29",20),
 (100,"2015-01-30",18),
 (101,"2015-01-14",30),
 (101,"2015-01-17",20)
) groupBy(_._1)

join(customers, purchases) mapValues { case (_, l) => l.map(_._3).sum }

您可以通过将join包含在隐式类中来实现implicit class C[K, A](a: Map[K, A]) { def join[B](b: Map[K, B]): Map[K, (A,B)] = for((k,va) <- a; vb <- b.get(k)) yield k -> (va, vb) } customers join purchases 中缀操作:

implicit class C[K, A](a: Map[K, A]) {

    def join[B](b: Map[K, B]): Map[K, (A,B)] =
        for((k,va) <- a; vb <- b.get(k)) yield k -> (va, vb)

    def leftJoin[B](b: Map[K, B], default: B): Map[K, (A,B)] =
        for((k,va) <- a; vb = b.getOrElse(k, default)) yield k -> (va, vb)

}

请注意,此连接实现(内部联接)很容易修改为表现为左连接:

customers leftJoin(purchases, Seq()) mapValues {
    case (_, l) => l.map(_._3).sum
}

> res: scala.collection.immutable.Map[Int,Int] = Map(100 -> 38, 101 -> 50, 102 -> 0)

然后将它与您的数据一起使用以获得您正在寻找的结果:

select p From Parent as p JOIN FETCH p.children as c where c.age >= 10

答案 1 :(得分:-1)

让我们来看看基础知识。内部和外部联接是数据库的SQL的一部分。如果您有SQL数据库,则可以使用Scala进行查询,并且可以执行连接操作。如果您将数据作为csv文件的集合,那么您需要一个引擎将其转换为支持RDBMS的SQL,然后可以进行连接。

换句话说,在Scala中,如在Java,C#或任何其他语言中,数据库是一个在开发过程中解决的实现细节。没有其他语言可以直接使用某种包装器AFAIK直接连接文件。

如果我必须做你在这里展示的内容,我会将我的csv文件导入SQL数据库,从SQLite到Oracle,SQL服务器,Mysql,接受你的选择,然后查询该数据库,最坏的情况通过JDBC。