我有这个scala方法,可以从一些参数构建Map:
def foo(name: Option[String], age: Option[Int], hasChilds: Option[Boolean],
childs: Option[List[Map[String, Any]]]): Map[String,Any] = {
var m = Map[String, Any]()
if (!name.isEmpty) m += ("name" -> name.get)
if (!age.isEmpty) m += ("age" -> age.get)
if (!hasChilds.isEmpty) m += ("hasChilds" -> hasChilds.get)
if (!childs.isEmpty) m += ("childs" -> childs.get)
m
}
我想知道是否有办法以更多功能的方式重构代码?
在这种情况下是否可以使用var
?
答案 0 :(得分:6)
一种方法包括扁平化不可变Map
,像这样,
def foo(name: Option[String],
age: Option[Int],
hasChilds: Option[Boolean],
childs: Option[List[Map[String, Any]]]): Map[String,Any] = {
Map( ("name" -> name),
("age" -> age),
("hasChilds" -> hasChilds),
("childs" -> childs)).collect { case(a,Some(b)) => (a,b) }
}
答案 1 :(得分:2)
另一种方法可以是
def foo(....) =
Map("name" -> name, "age" -> age, "hasChilds" -> hasChilds, "childs" -> childs)
.filter(_._2 != None).mapValues(_.get)
正如@Dider所指出的,这也可以做,类似于@enzyme solution
Map("name" -> name, "age" -> age, "hasChilds" -> hasChilds, "childs" -> childs)
.collect {case (k, Some(v)) => (k,v) }
答案 2 :(得分:0)
Scala通常支持键入的数据和不变性,并且您正在与这两者进行斗争。我不知道这张地图的背景是什么,但我认为使用带有可选参数的case clase会更加惯用。例如:
case class Person(name: String, age: Option[Int], children: Seq[Person]) {
def hasChildren: Boolean = !children.isEmpty
}
现在您可以使用可选的名称变量调用此方法。
val name: Option[String] = Option("suud")
val age: Option[Int] = Option(25)
val children: Seq[Person] = Seq.empty
val suud: Option[Person] = name map {Person(_, age, children)}
写入foo的方式,可以传入一个空的子列表,其中包含一个布尔参数,表示该地图有子项。编写hasChildren作为案例类的方法可以防止这种情况,因为布尔方法依赖于它所提供的有关信息的集合。
如果你真的坚持在这里使用地图,你可以使用MapBuilder来获取不可变的地图,或者只是导入并使用可变地图。
import scala.collection.mutable.MapBuilder
val builder: MapBuilder[String, Any, Map[String, Any]] = new MapBuilder(Map.empty)
if (!name.isEmpty) builder += ("name" -> name.get)
if (!age.isEmpty) builder += ("age" -> age.get)
if (!hasChilds.isEmpty) builder += ("hasChilds" -> hasChilds.get)
if (!childs.isEmpty) builder += ("childs" -> childs.get)
builder.result
现在构建器的结果是一个不可变的映射。如果你真的需要一个可变的地图,你可以:
import scala.collection.mutable
val m = mutable.Map[String, Any]()
现在您已经拥有了一个可变映射,可以使用toMap方法将其转换为不可变映射。