2015-10-04 20 views
5

有像數據:(燙)GROUPBY foldLeft使用組由值在摺疊

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

需要使它:

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

含義忽略來自第二柱自,和使以逗號分隔的字符串休息。它的製表符分隔數據

試過的變化,但不知道如何引用的productId在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; 
     } 
     } 
    } 
} 

使用Scala的2.10燙傷0.10.0和級聯2.5.3。需要一個燙傷答案。我知道如何操作scala中的數據。我只是想知道如何在羣組中通過燙傷來獲得列,並使用它們有條件地執行摺疊操作或使用其他方法來獲得過濾輸出。

對於一個完整的工作示例見https://github.com/tgkprog/scaldingEx2/tree/master/Q1

+0

爲什麼不使用文件管理器刪除自對,然後組由ID? – roterl

+0

是的工作,只是想在燙傷groupBy所以可以在同一階段過濾 – tgkprog

回答

1

只是一個groupBymap應該足以完成你想要的。

// 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))) 

我簡化了輸入/輸出表單,只是集中精力讓集合成爲正確的形式。

+0

好,但不可用。我需要解決燙傷api的問題。 – tgkprog

1

假設pid| recom-pid > temp.txt

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

我們轉換xs成元組,這樣

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

和組由第一要素,

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

然後我們刪除映射身份元組,確保總是地圖中的一個條目,其中一個空數組表示僅存在身份元組(即,的3|3獨特的發生會導致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

不錯但不可用。我需要解決燙傷api的問題。 – tgkprog

1

Asssuming你的字符串輸入是正確的,將返回一個Map [字符串,數組[字符串]

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

代替groupBy然後foldLeft,只使用foldLeft
下面是使用Scala集合一個解決方案,但它應該適用於使用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不是Pipe的成員。在文檔中看起來像是一個標題,但在減速器下 – tgkprog