Scala 如何有条件地应用一系列操作?
我有这样的逻辑,一个数据文件需要经历一系列的操作,但是是否需要一个操作是由一些布尔值控制的。基本上,数据数组通过流程循环并产生一些结果 我想知道是否有一种优雅的编码方式,希望不要使用Scala 如何有条件地应用一系列操作?,scala,Scala,我有这样的逻辑,一个数据文件需要经历一系列的操作,但是是否需要一个操作是由一些布尔值控制的。基本上,数据数组通过流程循环并产生一些结果 我想知道是否有一种优雅的编码方式,希望不要使用vars和大量if/else语句 def op1(data): Seq[int] def op2(data): Seq[int] def op3(data): Seq[int] def process(data: Seq[int], b1: boolean, b2: boolean, b3: boolean) =
var
s和大量if
/else
语句
def op1(data): Seq[int]
def op2(data): Seq[int]
def op3(data): Seq[int]
def process(data: Seq[int], b1: boolean, b2: boolean, b3: boolean) = {
//NOT working code, some thing does the following:
var temp: Seq[int] = data
if (b1)
temp = op1(temp)
if(b2)
temp = op2(temp)
if(b3)
temp = op3(temp)
temp
}在这种情况下,我实际上更喜欢您的解决方案,但这是一个更实用的替代方案。我用字符串替换了Seq,因为它们更容易用于示例,但这不重要
object SequenceOfOperations {
def op1(data: String) = data + "A" //> op1: (data: String)java.lang.String
def op2(data: String) = data + "B" //> op2: (data: String)java.lang.String
def op3(data: String) = data + "C" //> op3: (data: String)java.lang.String
def process(data: String, b1: Boolean, b2: Boolean, b3: Boolean) = {
val ops =Seq((b1 , op1(_)),(b2 , op2(_)),(b3 , op3(_)))
val filteredOps = ops.filter( _._1).map (_._2)
filteredOps.foldLeft(data)((l : String,o : String => String) => o(l))
} //> process: (data: String, b1: Boolean, b2: Boolean, b3: Boolean)String
process("Z", true, false, true) //> res0: String = ZAC
process("Y", true, true, false) //> res1: String = YAB
process("X", false, false, true) //> res2: String = XC
}
在这种情况下,我实际上更喜欢您的解决方案,但这是一个更实用的替代方案。我用字符串替换了Seq,因为它们更容易用于示例,但这不重要
object SequenceOfOperations {
def op1(data: String) = data + "A" //> op1: (data: String)java.lang.String
def op2(data: String) = data + "B" //> op2: (data: String)java.lang.String
def op3(data: String) = data + "C" //> op3: (data: String)java.lang.String
def process(data: String, b1: Boolean, b2: Boolean, b3: Boolean) = {
val ops =Seq((b1 , op1(_)),(b2 , op2(_)),(b3 , op3(_)))
val filteredOps = ops.filter( _._1).map (_._2)
filteredOps.foldLeft(data)((l : String,o : String => String) => o(l))
} //> process: (data: String, b1: Boolean, b2: Boolean, b3: Boolean)String
process("Z", true, false, true) //> res0: String = ZAC
process("Y", true, true, false) //> res1: String = YAB
process("X", false, false, true) //> res2: String = XC
}
这看起来像一个典型的折叠,您可以使用以下函数将其包装:
def maybeDo[A](bs: List[Boolean], fs: List[A => A], x: A) =
(bs zip fs).foldLeft(x) {
case (x, (b, f)) => if (b) f(x) else x
}
使用它的例子如下
> val bs = List(true, false, true)
> val fs: List[Int => Int] = List(_+1, _*3, _+2)
> maybeDo(bs, fs, 10)
res0: Int = 13
在您的示例中,它将类似于
val temp = maybeFold(List(b1, b2, b3), List(op1 _, op2 _, op3 _), data)
这看起来像一个典型的折叠,您可以使用以下函数将其包装:
def maybeDo[A](bs: List[Boolean], fs: List[A => A], x: A) =
(bs zip fs).foldLeft(x) {
case (x, (b, f)) => if (b) f(x) else x
}
使用它的例子如下
> val bs = List(true, false, true)
> val fs: List[Int => Int] = List(_+1, _*3, _+2)
> maybeDo(bs, fs, 10)
res0: Int = 13
在您的示例中,它将类似于
val temp = maybeFold(List(b1, b2, b3), List(op1 _, op2 _, op3 _), data)
有很多方法可以做到这一点 一种可能的方法是
def op1(data: Seq[Int]) = data.map(_ + 2) //your actual operation here..
def op2(data: Seq[Int]) = data.map(_ - 2) //..returning Seq[Int]
def op3(data: Seq[Int]) = data.map(_ * 2) //
implicit class SeqOps(val data: Seq[Int]) extends AnyVal {
def op(op: Seq[Int] => Seq[Int], b: Boolean) = if (b) op(data) else data
}
然后,def进程
可以写成
def process(data: Seq[Int], b1: Boolean, b2: Boolean, b3: Boolean) = {
data op (op1, b1) op (op2, b2) op (op3, b3)
}
有很多方法可以做到这一点 一种可能的方法是
def op1(data: Seq[Int]) = data.map(_ + 2) //your actual operation here..
def op2(data: Seq[Int]) = data.map(_ - 2) //..returning Seq[Int]
def op3(data: Seq[Int]) = data.map(_ * 2) //
implicit class SeqOps(val data: Seq[Int]) extends AnyVal {
def op(op: Seq[Int] => Seq[Int], b: Boolean) = if (b) op(data) else data
}
然后,def进程
可以写成
def process(data: Seq[Int], b1: Boolean, b2: Boolean, b3: Boolean) = {
data op (op1, b1) op (op2, b2) op (op3, b3)
}
假设您希望流程签名不更改
// continuing from the ops psuedocode
def process(data: Seq[Int], b1:Boolean, b2:Boolean, b3:Boolean): Seq[Int] = {
@tailrec
def loop (acc: Seq[Int], ops: List[Seq[Int] => Seq[Int]]): Seq[Int] = {
ops match {
case List () => acc
case head :: tail => loop (head(acc), tail)
}
}
loop (data, List(( b1,op1 _), (b2,op2 _),(b3,op3 _)).filter{ _._1 }.map{ _._2 })
}
解决方案是将op与正确的布尔值配对,在一个列表中,过滤掉带有不真实布尔值的对,将过滤后的对映射到op列表(基本上删除每个幸存对的布尔值部分),然后在输入数据上递归累积变换
下面是一些简单运算符的结果:
导入scala.annotations.tailrec
def op1(s: Seq[Int]) = s map {_ + 1}
def op2(s: Seq[Int]) = s map {_ * 2}
def op3(s: Seq[Int]) = s map {_ - 5}
def process(data: Seq[Int], b1:Boolean, b2:Boolean, b3:Boolean): Seq[Int] = {
@tailrec
def loop (acc: Seq[Int], ops: List[Seq[Int] => Seq[Int]]): Seq[Int] = {
ops match {
case List () => acc
case head :: tail => loop (head(acc), tail)
}
}
loop (data, List(( b1,op1 _), (b2,op2 _),(b3,op3 _)).filter{ _._1 }.map{ _._2 })
}
process(Seq(1,2,3), true, false, true) // Seq[Int] = List(-3, -2, -1)
process(Seq(1,2,3), true, false, false) // Seq[Int] = List(2, 3, 4)
process(Seq(1,2,3), false, true, false) // Seq[Int] = List(2, 4, 6)
假设您希望流程签名不更改
// continuing from the ops psuedocode
def process(data: Seq[Int], b1:Boolean, b2:Boolean, b3:Boolean): Seq[Int] = {
@tailrec
def loop (acc: Seq[Int], ops: List[Seq[Int] => Seq[Int]]): Seq[Int] = {
ops match {
case List () => acc
case head :: tail => loop (head(acc), tail)
}
}
loop (data, List(( b1,op1 _), (b2,op2 _),(b3,op3 _)).filter{ _._1 }.map{ _._2 })
}
解决方案是将op与正确的布尔值配对,在一个列表中,过滤掉带有不真实布尔值的对,将过滤后的对映射到op列表(基本上删除每个幸存对的布尔值部分),然后在输入数据上递归累积变换
下面是一些简单运算符的结果:
导入scala.annotations.tailrec
def op1(s: Seq[Int]) = s map {_ + 1}
def op2(s: Seq[Int]) = s map {_ * 2}
def op3(s: Seq[Int]) = s map {_ - 5}
def process(data: Seq[Int], b1:Boolean, b2:Boolean, b3:Boolean): Seq[Int] = {
@tailrec
def loop (acc: Seq[Int], ops: List[Seq[Int] => Seq[Int]]): Seq[Int] = {
ops match {
case List () => acc
case head :: tail => loop (head(acc), tail)
}
}
loop (data, List(( b1,op1 _), (b2,op2 _),(b3,op3 _)).filter{ _._1 }.map{ _._2 })
}
process(Seq(1,2,3), true, false, true) // Seq[Int] = List(-3, -2, -1)
process(Seq(1,2,3), true, false, false) // Seq[Int] = List(2, 3, 4)
process(Seq(1,2,3), false, true, false) // Seq[Int] = List(2, 4, 6)
你能有一个函数列表和一个布尔值列表吗?你能有一个函数列表和一个布尔值列表吗?电话输入很糟糕。丢失了代码块中的所有换行符。Meta:如何修复?从标记中删除
标记选择您的代码块,如果您正在使用mac,请按CTRL+K或CMD+K,或者用'code'手机条目将代码块包装起来。丢失了代码块中的所有换行符。Meta:如何修复?从标记中删除标记选择您的代码块,如果您正在使用mac,请按CTRL+K或CMD+K,或者仅用`code'包装您的代码块`