2

我是 scala 的初学者,正在寻找最好的/惯用的方式来做我打算在这里做的事情。

这就是我想做的

def someMethod(obj:MyObj):List[String] = {
     List[String]() +: 
      {if (somecondition is satisfied) .. " element"} +: 
      { if (another condition) .. " something else " }


}

即该方法检查输入参数对象的某些属性并将元素添加到列表(即要返回)。如果不满足任何条件,它应该返回一个空列表。

  1. 当然,代码不会编译。但不知何故,对我来说 List[T] + Unit 应该返回 List[T] 似乎很直观。为什么我错了?

2. 请告诉我做这个 Scala 的正确方法。如果我正在迭代一个条件列表,我可以使用推导式。

4

4 回答 4

4

而不是过滤单元,我宁愿使用一元或空列表:

def someMethod(obj:MyObj): List[String] = {
    Nil ++
    ( if (somecondition is satisfied) List(" element") else Nil ) ++
    ( if (another condition) .. List(" something else ") else Nil ) ++
}

编辑:关于您在下面的评论,如果您发现上面的代码过于冗长且难以维护,您仍然可以创建一个辅助函数:

def optElem[T]( condition: Boolean)( value: => T ): Option[T] = if ( condition ) Option( value ) else None
def someMethod(obj:MyObj): List[String] = {
  Nil ++
  optElem (somecondition is satisfied)( " element") ++
  optElem (another condition)(" something else " )
}
于 2012-09-13T08:43:52.383 回答
3

if-else是 Scala 中的表达式。你写的变成:

List[String]() +: 
      {if (somecondition is satisfied) {" element"; () } else () }+: 
      { if (another condition) { " something else "; () } else () }

如您所见,常见的分支类型是Unit.

整个表达式的类型将是,因为这是andList[Any]的常见超类型。StringUnit

实现您想要的一些方法:

// #1. Ugly.
def someMethod(obj:MyObj):List[String] = {
  val xs = List[String]() 
  val xs1 = if (somecondition is satisfied) xs :+ " element" else xs
  val xs2 = if (another condition) xs1 :+ " something else" else xs1
  xs2
}

// #2. Better, but uses mutable builder.
def someMethod(obj:MyObj):List[String] = {
  val b = List.newBuilder[String]
  if (somecondition is satisfied) b += " element"
  if (another condition) b += " something else"
  b.result
} 

// #3. Best way IMO, but computationally expensive.
def someMethod(obj:MyObj):List[String] = {
  List[String]() ++
  Option("element").filter(some condition) ++ // for more correct semantics
                                              // use LazyOption from Scalaz.
  Option("something else").filter(another condition)
} 
于 2012-09-13T08:39:24.620 回答
2

你可以这样写:

def someMethod(obj:MyObj):List[String] = {
     List(
      if (somecondition is satisfied) " element", 
      if (another condition) " something else "
     ) collect{ case x: String => x }
}

假设所有条件都失败了:你最终List(Unit,Unit)会得到 first ,它将按类型过滤。单位不满足收集内部的类型条件,因此结果将为空字符串列表

好消息是,不同的filter方法collect选择尽可能紧凑的类型(所以你会得到字符串序列——这将是从 collect 内部的函数推断出来的)。

另一种可能性是替换.collect { ... }flatten,但您会丢失类型信息。

于 2012-09-13T08:27:15.253 回答
1

对此的另一种看法是构建一个选项列表,然后将列表展平。

def f(obj: MyObj): List[String] = {
  List(if (cond1(obj)) Some("element")        else None,
       if (cond2(obj)) Some("something else") else None).flatten
}
于 2012-09-13T12:12:11.537 回答