我有两个布尔值,b1
和b2
,我想从它们中创建一个字符串,如下所示:
--> str = "b1" # if b1 is true and b2 is false
--> str = "b2" # if b2 is true and b1 is false
--> str = "b1, b2" # if both are true
--> str = "" # if both are false
我在Scala中编写它的最简单方法是什么?
这是我的第一次尝试:
val b1str: String = if(b1) "b1" else ""
val b2str: String = if(b2) "b2" else ""
val str = List(b1str, b2str).mkString(",")
这很难看,甚至不起作用。
答案 0 :(得分:3)
这是一个推广到两个以上元素的解决方案:
List(b1, b2)
.zip(Stream from 1 map ("b" + _))
.collect({ case (true, s) => s })
.mkString(",")
但是,如果您所做的事情与该抽象不匹配,那么仅使用模式匹配来枚举所有四种情况可能更合适:
(b1, b2) match {
case (true, true) => "b1,b2"
case (true, false) => "b1"
case (false, true) => "b2"
case (false, false) => ""
}
答案 1 :(得分:1)
这个怎么样?
List((b1,"b1"), (b2,"b2")).collect { case (b,s) if b => s }.mkString(",")
答案 2 :(得分:1)
这不是一个理智的方法。无论你做什么,都不要投票。但它确实有效。它适用于任意数量的布尔变量,您不必在字符串文字中重复变量的名称,它处理任意布尔表达式以及变量,并且调用代码非常易读。
这是一个宏,commaSeparatedTrueExprs
。把它放在一个单独的文件中:
// requires Scala 2.11
import scala.reflect.runtime.universe._
import reflect.macros.whitebox.Context
import language.experimental.macros
object commaSeparatedTrueExprs {
def apply(exprs: Any*): String = macro impl
def impl(c: Context)(exprs: c.Tree*) = { import c.universe._
val elems = exprs map { expr =>
val s = showCode(expr)
q"if ($expr) Some($s) else None"
}
q"""Seq(..$elems).flatten.mkString(", ")"""
}
}
然后这个调用代码:
for (b1 <- Seq(false, true); b2 <- Seq(false, true))
println(commaSeparatedTrueExprs(b1, b2))
生成此输出:
b2
b1
b1, b2
这是调用代码,用于说明将任意表达式传递给commaSeparatedTrueExprs
:
val b1 = true
val b2 = false
println(commaSeparatedTrueExprs(b1, b2, b1 && b2, b1 || b2, true, false))
输出结果为:
b1, b1.||(b2), true
答案 3 :(得分:0)
以下方法提取关联谓词求值为true的字符串;然后附加这样的字符串。
让
val a = List( (true,"b1"), (false,"b2"), (true,"b3") )
然后采用类似的(等效的)收集方法,
a.view.filter( _._1 ).map( _._2 ).mkString(",")
res: String = b1,b3
或用于理解
val b = for ( (b,v) <- a if b ) yield v
b: List[String] = List(b1, b3)
b.mkString(",")
res: String = b1,b3