Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何有条件地应用一系列操作?_Scala - Fatal编程技术网

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'包装您的代码块`