0

下面的程序假设计算一个可能有两种不同数据类型的表达式,FloatRDD。我已经从中缀表达式创建了一个 RPN,现在我正在尝试对它们执行计算。注意:我还重载了 :+,-,/,* 用于对RDD和进行计算float

 def calcRPN(s: String): RDD[(Int,Array[Float])] =
     (s.split(' ').toList.foldLeft(Nil: List[Either[Float, RDD[(Int,Array[Float])]]) {foldingFunction}).head

def foldingFunction(list: List[Either[Float, RDD[(Int,Array[Float])]]], next: String): List[Either[Float,RDD[(Int,Array[Float])]]] = (list, next) match {
     //apply * on inputs
     case (Right(x) :: Right(y) :: ys, "*") =>{(sv.*(x,y)) :: ys}                                   //both RDD sv is another class containing overloads
     case (Left(x) :: Right(y) :: ys, "*") =>{sv.*(x,y) :: ys} //x being float
     case (Right(x) :: Left(y) :: ys, "*") =>{sv.*(x,y) :: ys} //y being float}
     case (Left(x) :: Left(y) :: ys, "*") => (x * y) :: ys                                                      //both float
     //apply + on inputs
     case (Right(x) :: Right(y) :: ys, "+") => {(sv.+(x,y)) :: ys}                              //both RDD
     case (Left(x) :: Right(y) :: ys, "+") =>{(sv.+(x,y)):: ys} //x being float
     case (Right(x) :: Left(y) :: ys, "+") =>{(sv.+(x,y)):: ys} //y being float
     case (Left(x) :: Left(y) :: ys, "+") => (y + x) :: ys                                                      //both float
     //apply - on the inputs
     case (Right(x) :: Right(y) :: ys, "-") => {(sv.-(x,y)):: ys}                               //both RDD
     case (Left(x) :: Right(y) :: ys, "-") =>{(sv.-(x,y)) :: ys} //x being float
     case (Right(x) :: Left(y) :: ys, "-") =>{(sv.-(x,y)):: ys} //y being float
     case (Left(x) :: Left(y) :: ys, "-") => (y - x) :: ys                                                      //both float
     //apply / on the inputs
     case (Right(x) :: Right(y) :: ys, "/") => {(sv./(x,y)) :: ys}                              //both RDD
     case (Left(x) :: Right(y) :: ys, "/") =>{(sv./(x,y)) :: ys} //x being float
     case (Right(x) :: Left(y) :: ys, "/") =>{(sv./(x,y)):: ys} //y being float
     case (Left(x) :: Left(y) :: ys, "/") => {(y / x) :: ys}                                                        //both float
     case (xs, numString) => numString.toInt :: xs  //**
     case (xs, pathxml) => sv.getArrayRDD() :: xs //***

   }

我知道这段代码很抱歉。我可以让它更短,但现在我需要让它工作,然后把它刷起来!所以在 ** 部分它适用于两个数字,但我添加了 *** 以使其也接受RDD。不知道它是否适用于FloatRDDEither另外,由于使用and 显然我遇到了以下错误,Left并且Right在这里没有帮助我!

 [error] type mismatch;
 [error]  found   : Either[Float,org.apache.spark.rdd.RDD[(Int, Array[Float])]]
 [error]  required: org.apache.spark.rdd.RDD[(Int, Array[Float])]
 [error]         (s.split(' ').toList.foldLeft(Nil: List[Either[Float, RDD[(Int,Array[Float])]]]) {foldingFunction}).head
 [error]                                                                                                             ^

我也试过Scalaz,但它使它更复杂。

4

1 回答 1

1

好的,首先,让我们分开一些事情以便更好地理解:

val creepyListOfoperatorsAndStuff: List[String] = s.split(' ').toList

val eitherList: List[Either[Float, RDD[(Int,Array[Float])]]] = 
  creepyListOfoperatorsAndStuff.foldLeft(
    List.empty[Either[Float, RDD[(Int,Array[Float])]]
  ) (foldingFunction)

val headEither:Either[Float, RDD[(Int,Array[Float])]] = eitherList.head

该列表的头部是一个 Either。因此既不是 Float 也不是 RDD。这意味着我们必须决定它是 Float 还是 RDD[(Int,Array[Float])]。如果你真的确定 head 包含一个 RDD,你可以这样做:

headEither.right.get

更好的方法可能是同时处理这两种情况:

headEither.fold[RDD[(Int,Array[Float])]](
  // function to convert a Left() result to the RDD you want
  fa = someFloat => <code to get to the RDD you want>, 
  // this is a function to transform the Right() result to what is desired 
  // as RDD is what you want you can just return the input
  fb = anRDD => anRDD
)

现在转到案例**和***:

case (xs, numString) => numString.toInt :: xs  //**
case (xs, pathxml) => sv.getArrayRDD() :: xs //***

第二种情况似乎无法到达,因为两种情况都匹配相同的输入。您最好使用正则表达式来匹配您期望的字符串。我不是正则表达式匹配方面的专家,但类似以下内容可能指向正确的方向。

val Numeric = """(\d+)""".r
// don't forget to put the matched string into a group
val XmlPath = """<some regular expression that matches your expected xml path""".r

...

case (xs, NumericString(numString)) => numString.toInt :: xs  //**
case (xs, XmlPath(pathxml)) => sv.getArrayRDD() :: xs //***

但是,这两种情况存在更本质的问题:

case (xs, numString) => numString.toInt :: xs  //**

xs 将是一个 List[Either[Float, RDD[(Int,Array[Float])]]。因此我不得不怀疑,这是否编译?

numString.toInt :: xs 

如果是这样,那么 numString.toInt 可能会转换为 Float,然后再转换为 Left[Float]。但我只是猜测。

case (xs, pathxml) => sv.getArrayRDD() :: xs //***

虽然我看不到sv可能是什么以及它的形成方式,但使用正则表达式匹配器可能没问题。

我只能通过您提供的更多信息来提供帮助。

于 2015-07-17T16:37:26.087 回答