2015-10-04 14 views
5

dispone di dati come:(scottatura) groupBy foldLeft utilizzando il gruppo dal valore nella piega

pid recom-pid 
1 1 
1 2 
1 3 
2 1 
2 2 
2 4 
2 5 

necessario rendere:

pid, recommendations 
1 2,3 
2 1,4,5 

Significato ignorare auto dal 2 ° colonna, e rendere il riposa in una stringa separata da virgole. La linguetta separati dati

provato variazioni, ma non so come fare riferimento a productId nel foldLeft

.groupBy('productId) {  
    _.foldLeft(('prodReco) -> 'prodsR)("") { 
    (s: String, s2: String) => 
     { 
     println(" s " + s + ", s2 :" + s2 + "; pid :" + productId + ".") 
     if (productId.equals(s2)) { 
      s 
     } else { 
      s + "," + s2; 
     } 
     } 
    } 
} 

Uso scala 2.10 con scottatura 0.10.0 e cascata 2.5.3. Hai bisogno di una risposta scottante. So come manipolare i dati in scala. Mi sto solo chiedendo come afferrare le colonne durante il raggruppamento in scottature e usarle per fare condizionalmente una piega a sinistra o altri mezzi per ottenere l'output filtrato.

Per un esempio completo vedere https://github.com/tgkprog/scaldingEx2/tree/master/Q1

+0

perché non utilizzare filer per rimuovere le coppie di auto e quindi di gruppo da parte della id? – roterl

+0

Sì, funziona, volevo solo qualcosa nel gruppo scottatura. Così può filtrare nella stessa fase – tgkprog

risposta

1

Solo un groupBy e un map dovrebbe essere sufficiente a realizzare ciò che si desidera.

// Input data formatted as a list of tuples. 
val tt = Seq((1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 4), (2, 5)) 

tt 
    .groupBy(_._1) // Map(2 -> List((2, 1), ...), 1 -> List((1, 1), ...)) 
    .toSeq // for easier mapping 
    .map({ 
    case (pid, recomPids) => { 
     val pids = recomPids.collect({ 
     case recomPid if recomPid._2 != pid => recomPid._2 
     }) 
     (pid, pids) 
    } 
    }) // List((2, List(1, 4, 5)), (1, List(2, 3))) 

Ho semplificato il modulo di input/output per concentrarmi solo su come ottenere le raccolte nella forma corretta.

+0

Bello ma non utilizzabile. Ho bisogno di una soluzione in api scottanti. – tgkprog

1

assuma pid| recom-pid > temp.txt e così

import scala.io.Source 
val xs = Source.fromFile("temp.txt").getLines.toArray.map(_.split("\\|")) 

convertiamo xs in tuple, come questo

val pairs = for (Array(pid, recom) <- xs) yield (pid,recom) 
Array((1,1), (1,2), (1,3), (2,1), (2,2), (2,4), (2,5)) 

e il gruppo dal primo elemento,

val g = pairs.groupBy(_._1) 
Map(2 -> Array((2,1), (2,2), (2,4), (2,5)), 1 -> Array((1,1), (1,2), (1,3))) 

Poi abbiamo rimuovere mappato identità tuple, che garantisce sempre una voce nella mappa, dove un array vuoto indica che c'era solo la tupla dell'identità (vale a dire. occorrenza unica di 3|3 porterebbe a 3 -> Array()),

val res = g.mapValues(_.filter { case (a,b) => a != b }) 
Map(2 -> Array((2,1), (2,4), (2,5)), 1 -> Array((1,2), (1,3))) 
+0

Bello ma non utilizzabile. Ho bisogno di una soluzione in api scottanti. – tgkprog

1

Asssuming l'input stringa è giusto che restituisce una mappa [String, Array [String]]

s.split('\n') 
.map(_.split("\\|")) 
.groupBy(_(0)) 
.mapValues(_.flatten) 
.transform {case (k, v) ⇒ v.filter(_ != k)} 
2

Invece di groupBy e poi foldLeft, utilizzare solo foldLeft.
Ecco una soluzione che utilizza collezioni Scala ma dovrebbe funziona utilizzando scalading as well:

val source = List((1,1), (1,2), (1,3), (2,1), (2,2), (2,4), (2,5))                     
source.foldLeft(Map[Int, List[Int]]())((m,e) =>         
    if (e._1 == e._2) m else m + (e._1 -> (e._2 :: m.getOrElse(e._1, List())))) 
+0

foldLeft non è membro di Pipe. Sembra che nei documenti sia lì come un titolo ma è sotto i riduttori – tgkprog