如何在 Scala 中计算具有两种不同数据类型的 RPN 表达式?
How to calculate a RPN expression having two different data types in Scala?
下面的程序假设计算一个可能有两种不同数据类型的表达式,Float
和 RDD
。我已经从中缀表达式创建了一个 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
。不知道它是否适用于 Float
和 RDD
!另外,由于使用 Either
,我遇到了以下错误,显然 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
但它使它变得更复杂。
好的,首先,让我们把事情分开以便更好地理解:
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 可能是什么以及它的形式,但可能没问题,使用正则表达式匹配器。
只有从您那里获得更多信息,我才能提供帮助。
下面的程序假设计算一个可能有两种不同数据类型的表达式,Float
和 RDD
。我已经从中缀表达式创建了一个 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
。不知道它是否适用于 Float
和 RDD
!另外,由于使用 Either
,我遇到了以下错误,显然 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
但它使它变得更复杂。
好的,首先,让我们把事情分开以便更好地理解:
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 可能是什么以及它的形式,但可能没问题,使用正则表达式匹配器。
只有从您那里获得更多信息,我才能提供帮助。