如何在Scala中计算具有两种不同数据类型的RPN表达式? [英] How to calculate a RPN expression having two different data types in Scala?

查看:90
本文介绍了如何在Scala中计算具有两种不同数据类型的RPN表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following program is suppose to calculate an expression with the possibility of having two different data types , Float and RDD. I already created an RPN from the infix expression and now I am trying to perform calculations on them. Note: I have also overloaded :+,-,/,* for doing calculations on RDD and 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.不知道它是否对FloatRDD均适用!另外,由于使用Either我遇到了以下错误,显然LeftRight在这里没有帮助我!

I know this code is ugly sorry about that. I can make it shorter but right now I need to make it work then brush it up! So in the ** part it is working for two numbers but I added *** to make it accept RDD as well. Don't know if it works for both Float and RDD! plus I have faced the following error because of using Either and apparently Left and Right are not helping me here!

 [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,但是它变得更加复杂.

I also tried Scalaz but it made it more complex.

推荐答案

首先要确定,为了更好的理解,让我们分解一下内容:

Ok first things first, lets split up things for a better understanding:

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])]. 如果您真的确定磁头包含RDD,则可以执行以下操作:

The head of that List is an Either. Thus neither a Float nor a RDD. That means we have to decide whether it is a Float or a RDD[(Int,Array[Float])]. If you are REALLY sure head contains an RDD, you can just do:

headEither.right.get

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

A better way to do this might be to deal with both cases:

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
)

现在开始处理**和***:

Now onwards to the cases ** and ***:

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

第二种情况似乎无法实现,因为这两种情况都匹配相同的输入.使用正则表达式匹配您在那里期望的字符串可能会更好.我不是正则表达式匹配的专家,但是类似以下内容的内容可能会指向正确的方向.

The second case seems unreachable, because both cases match the same input. You would probably be better off using regex to match the strings you expect there. I am not exactly an expert on regular expression matching but something like the following might point in the right direction.

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

但是,在这两种情况下,还有一些更重要的问题:

However, there are more essential problems in theses two cases:

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

xs将是一个List [Either [Float,RDD [(Int,Array [Float])]]. 因此,我想知道,这可以编译吗?

xs would be a List[Either[Float, RDD[(Int,Array[Float])]]. Thus I have to wonder, does this compile?

numString.toInt :: xs 

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

If so then numString.toInt is probably converted to Float and then to Left[Float]. But I'm just guessing.

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

虽然我看不到 sv 可能是什么,以及它来自何处,但使用正则表达式匹配器还是可以的.

While I donn't see what sv might possibley be and where it comes form, it might be ok, with the regex matcher.

只有您提供更多信息,我才能为您提供帮助.

I would only be able to help with that with more information form you.

这篇关于如何在Scala中计算具有两种不同数据类型的RPN表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆