2016-08-19 3 views
1

Я работаю над простым требованием, чтобы узнать totalSpent каждым клиентом. Если Клиент ничего не тратить, то мне нужно, чтобы отобразить TotalSpent Сумму как 0 емуПоиск TotalSpent для каждого клиента в Scala

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 

ли мы просто присоединиться ключевые слова в Скале? Если нам нужно получить значения на основе общего ключа между двумя файлами, мы не можем использовать что-то вроде Join (internal join, left join) в scala?

Здесь я использую карту коллекции scala и перебираю ее по отношению к каждому клиенту.

Можем ли мы достичь этого же требования с помощью простых строк кода scala?

ответ

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 

Обратите внимание, что эта реализация объединения (внутреннее соединение) легко модифицируется для b ehave как левый присоединиться:

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) 
+0

def join [K, A, B] (a: Карта [K, A], b: Карта [K, B]): Карта [K, (A, B)] = для ((k, va) < - a; vb <- b.get (k)) дают k -> (va, vb). Здесь, Какое использование квадратных скобок соединяется [K, A, B]? , также этот метод возвращает Map. Тип для значения возвращаемой карты - Tuple? –

+0

@SurenderRaja Что находится внутри квадратных скобок - это параметры типа метода, которые есть там, чтобы заставить его работать с картами, имеющими любой тип ключа и значение. –

+0

@SurenderRaja В результате получается кортеж, содержащий объединенное значение. Какой тип можно использовать для хранения двух экземпляров разных типов? Кортеж. Например: у вас есть карта из целого числа в строку, а другая - из целого числа в double. Если вы присоединяетесь к ним, единственным приемлемым типом результата для результирующих значений карты является (String, Double) –

-1

Давайте рассмотрим основы. Внутренние и внешние соединения являются частью SQL для баз данных. Если у вас есть база данных SQL, вы можете использовать Scala для ее запроса, и вы можете выполнять операции объединения. Если у вас есть данные в виде коллекции csv-файлов, вам нужен движок, который превращает его в SQL-поддержку RDBMS, а затем может выполнять объединения.

Другими словами, в Scala, как и в Java, C# или на любом другом языке, база данных представляет собой деталь реализации, которая разрабатывается во время разработки. Ни один другой язык не может напрямую присоединяться к файлам, сначала используя какой-то обертку AFAIK.

Если бы мне пришлось делать то, что вы здесь показываете, я бы импортировал файлы csv в базу данных SQL, от SQLite до Oracle, SQL-сервера, Mysql, take-your-pick, а затем запросил эту базу данных в худшем случае сценария через JDBC.

+0

Соединить операция - как понятие - выходы вне SQL. Вы можете реализовать операции объединения для структур данных ключевого значения на любом языке. После того, как OP загружает свои данные в такую ​​структуру данных из файлов TXT, использование внешней службы просто для того, чтобы выполнить соединение, кажется немного переборщиком. –

+0

Это не очень полезный ответ. Как отмечает @ PabloFranciscoPérezHidalgo, 'join' не уникален для SQL и может быть легко выполнен в scala, как указывает другой ответ. –

+0

Конечно. не стесняйтесь использовать все, с чем вы не согласны лично. однако, Join - это, по сути, концепция базы данных отношений. тот факт, что вы можете имитировать его путем прохождения двух списков, является универсальным и вовсе не специфичен для Scala. Как я уже сказал в своем ответе, вам нужно внедрить обертку, что и сделал другой ответ. Я могу сделать это на любом языке. с некоторой практикой, я уверен, что вы тоже. – Reza

Смежные вопросы