(烫伤)groupBy foldLeft使用折叠组中的值

时间:2015-10-04 22:58:49

标签: scalding

拥有以下数据:

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

含义忽略第二列中的self,并将其余部分放入逗号分隔的字符串中。其标签分隔数据

尝试了变体,但不确定如何在foldLeft中引用productId

.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

4 个答案:

答案 0 :(得分: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()))))  

答案 1 :(得分: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)))

我简化了输入/输出表单,专注于将集合转换为正确的形式。

答案 2 :(得分: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)))

答案 3 :(得分:1)

假设您的字符串输入正确,返回Map [String,Array [String]]

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