如何避免此构建器中的任何可变事物?

时间:2014-06-06 02:10:14

标签: 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 """)
    } // 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)

result内容取决于所选过滤器的性质及其关联和硬编码表达式(String)。

有没有办法通过删除这个" mutability"来转换这段代码片段? mutable.Map的?

3 个答案:

答案 0 :(得分:2)

由于Map中最多有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)

答案 1 :(得分:2)

将结果添加到Seq时,将每个过滤器字段映射到元组,然后使用None过滤掉flatten,最后将Seq元组转换为Map toMap。{。} 要添加更多字段进行过滤,您只需在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
    }

希望它有所帮助。
加斯。

答案 2 :(得分:0)

我已经成功实现了这个解决方案:

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 """))

}

有更好的方法吗?