带有收益的平面图后,Scala Spark无法访问元组

时间:2018-10-13 02:41:05

标签: scala apache-spark tuples yield flatmap

    val test_rated = pearson.flatMap(x => {
        val bid1 = x._1._1.toInt
        val bid2 = x._1._2.toInt
        val sim = x._2.toDouble

        val pairs = for (tu <- test_users) yield {
            val tid = tu.toInt
            if (test_map.contains((tid, bid2)) && train_map.contains((tid, bid1))){
                ((tid, bid2), (bid1, sim))
            }
        }
        pairs
    }).filter(row => row!= ())

在此代码块test_users中是标量list。经过flatMap的yield操作之后,我可以得到结果并用foreach打印。 但是,如果我想再次映射它

test_rated.map(x => x._2)

我无法使用x._2

访问每个单独的元组值

2 个答案:

答案 0 :(得分:1)

假设其余代码正确且类型匹配(如果没有[mcve],则不可能说),这只是在以错误的方式进行操作。让我们简化显示原因的过程:

scala> for {
     | x <- 1 to 5
     | } yield { if (x % 2 == 0) x}
res0: scala.collection.immutable.IndexedSeq[AnyVal] = Vector((), 2, (), 4, ())

您看到的类型不是Seq[Int],而是Seq[AnyVal]。过滤数据不会改变:

scala> res0.filter(x => x != ())
res1: scala.collection.immutable.IndexedSeq[AnyVal] = Vector(2, 4)

您可以collect

scala> res0.collect { case x: Int => x}
res2: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4)

但实际上您应该使用保护表达式:

scala> for {
     | x <- 1 to 5 if x % 2 == 0
     | } yield x
res3: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4)

因此您的代码应重写为:

val test_rated = pearson.flatMap(x => {
    val bid1 = x._1._1.toInt
    val bid2 = x._1._2.toInt
    val sim = x._2.toDouble

    def keep(tid) = {
      test_map.contains((tid, bid2)) && train_map.contains((tid, bid1))
    }

    for {
      tid <- test_users.map(_.toInt) if keep(tid)
    } yield ((tid, bid2), (bid1, sim))
})

答案 1 :(得分:0)

我相信flatMap()中的代码块不会对任何对象求值。您应该删除val pairs =或显式返回pairs,例如

pearson.flatMap(x => { 
  ... 
  val pairs = ...
  pairs
}).filter(...)