Scala 如何避免此生成器中的任何可变内容?

Scala 如何避免此生成器中的任何可变内容?,scala,functional-programming,immutability,Scala,Functional Programming,Immutability,我有一个简单的Scala类,如下所示: class FiltersBuilder { def build(filter: CommandFilter) = { val result = collection.mutable.Map[String, String]() if (filter.activity.isDefined) { result += ("activity" -> """ some specific expression """)

我有一个简单的Scala类,如下所示:

class FiltersBuilder {

  def build(filter: CommandFilter) = {
    val result = collection.mutable.Map[String, String]()
    if (filter.activity.isDefined) {
      result += ("activity" -> """ some specific expression """)
    } // I well know that manipulating option like this is not recommanded, 
      //it's just for the simplicity of the  example
    if (filter.gender.isDefined) {
      result += ("gender" -> """ some specific expression """)
    }
    result.toMap //in order to return an immutable Map
  }
}
使用该类以便:

case class CommandFilter(activity: Option[String] = None, gender: Option[String] = None)
结果
内容取决于所选筛选器及其关联和硬编码表达式(
字符串
)的性质


是否有方法通过删除
mutable.Map
)的“可变性”来转换此代码段

我刚刚通过这个解决方案实现了这一点:

class FiltersBuilder(commandFilter: CommandFilter) {

   def build = {
     val result = Map[String, String]()
     buildGenderFilter(buildActivityFilter(result))
   }

   private def buildActivityFilter(expressions: Map[String, String]) =
     commandFilter.activity.fold(expressions)(activity => result + ("activity" -> """ expression regarding activity """))

   private def buildGenderFilter(expressions: Map[String, String]) =
     commandFilter.gender.fold(expressions)(gender => result + ("gender" -> """ expression regarding gender """))

}

有更好的方法吗?

我刚刚用这个解决方案实现了:

class FiltersBuilder(commandFilter: CommandFilter) {

   def build = {
     val result = Map[String, String]()
     buildGenderFilter(buildActivityFilter(result))
   }

   private def buildActivityFilter(expressions: Map[String, String]) =
     commandFilter.activity.fold(expressions)(activity => result + ("activity" -> """ expression regarding activity """))

   private def buildGenderFilter(expressions: Map[String, String]) =
     commandFilter.gender.fold(expressions)(gender => result + ("gender" -> """ expression regarding gender """))

}

有更好的方法吗?

因为您的
地图中最多有2个元素

val activity = filter.activity.map(_ => Map("activity" -> "xx"))
val gender = filter.gender.map(_ => Map("gender" -> "xx"))
val empty = Map[String, String]()
activity.getOrElse(empty) ++ gender.getOrElse(empty)

由于
地图中最多有2个元素

val activity = filter.activity.map(_ => Map("activity" -> "xx"))
val gender = filter.gender.map(_ => Map("gender" -> "xx"))
val empty = Map[String, String]()
activity.getOrElse(empty) ++ gender.getOrElse(empty)

将结果添加到
Seq
时,将每个过滤器字段映射到一个元组,然后使用
flatten
过滤掉
None
s,最后使用
toMap
Seq
元组转换为
Map

要添加更多要筛选的字段,只需在
Seq

    def build(filter: CommandFilter) = {
      // map each filter filed to the proper tuple
      // as they are options, map will transform just the Some and let the None as None
      val result = Seq(
        filter.activity.map(value => "activity" -> s""" some specific expression using $value """),
        filter.gender.map(value => "gender" -> s""" some specific expression using $value """)
      ).flatten // flatten will filter out all the Nones
      result.toMap // transform list of tuple to a map
    }
希望有帮助。

加斯顿。

将结果添加到
Seq
时,将每个过滤字段映射到一个元组,然后使用
flatten
过滤掉
None
s,最后使用
toMap将元组的
Seq
转换为
Map

要添加更多要筛选的字段,只需在
Seq

    def build(filter: CommandFilter) = {
      // map each filter filed to the proper tuple
      // as they are options, map will transform just the Some and let the None as None
      val result = Seq(
        filter.activity.map(value => "activity" -> s""" some specific expression using $value """),
        filter.gender.map(value => "gender" -> s""" some specific expression using $value """)
      ).flatten // flatten will filter out all the Nones
      result.toMap // transform list of tuple to a map
    }
希望有帮助。
加斯顿