我想简化一下:
var countA: Int = 0
var countB: Int = 0
if (validItem) {
if (region.equalsIgnoreCase( "US" )) {
if (itemList > 0) {
countB = 1
} else {
countA = 1
}
} else {
countB = 1
}
} else {
countA = 1
}
如何在 Scala 中使用三元条件运算符?
您不需要在 Scala 中使用三元运算符。在 Scala 中,
if
是一个表达式而不是一个语句,你可以说 val x = if (b) 1 else 2
。
在您的示例中使用
var
也指出了一个问题,因为当您使用 if
作为表达式时,通常可以避免这种情况。
让我们尝试分解代码以避免
var
,即首先删除所有不是具有相应 if
的表达式的 else
语句,并始终提供两个值:
var countA: Int = ???
var countB: Int = ???
if (validItem) {
if (region.equalsIgnoreCase("US")) {
if (itemList > 0) {
countA = 0
countB = 1
} else {
countA = 1
countB = 0
}
} else {
countA = 0
countB = 1
}
} else {
countA = 1
countB = 0
}
现在我们可以定义
countA
和 countB
之一为 1 的条件:
val isUS = region.equalsIgnoreCase("US")
val hasItems = itemList > 0
val isA = !validItem || (isUS && !hasItems)
val isB = !isA
// or: val isB = validItem && (!isUS || hasItems)
然后:
val countA = if (isA) 1 else 0
val countB = if (isB) 1 else 0
?:
三元条件运算符。尽管您可以使用隐式来模仿语法(请参阅@jwvh的answer),但我认为它并没有真正简化任何事情。
传统的技术有几个重要的特性
?:
它总是有两个分支
根据上一个属性,三元运算符总是返回一个值(这主要是使用
?:
的目的)
val result: Int = if (true) 1 else 2
// result is 1
分支被评估惰性
if (true) 1 else (0/0) // returns 1
if (false) 0/0 else 2 // returns 2
// i.e. 0/0 is not evaluated
如您所见,在 Scala
if-else
(带有 else
)构造满足这些属性。对于其他一些语言(如 C 或 Java)中的 if-else
构造来说,情况并非如此,因为它不返回值。
所以最重要的是,在
Scala
中你不需要三元运算符,因为你可以只使用 if-else
。
注:
正如 Alexey Romanov 在评论中提到的那样,没有
if
的 else
语句实际上也满足了第一个条件。当你写的时候
val result = if (true) 1
它实际上意味着
if (true) 1 else ()
,因此 result
将具有类型 AnyVal
而不是 Int
,因为 if
表达式的返回类型是两个分支(Int
和 Unit
)的最低公共界限
在这种情况下)。
这对于“新手”来说可能有点令人困惑,但是您可以像这样将三元方法附加到
Boolean
类。
implicit class Ternary[T](condition: Boolean) {
def ??(a: => T, b: => T): T = if (condition) a else b
}
用途:
(4 == 4)??("yes","no") // res0: String = yes
("abc".length < 2).??(1,0) // res1: Int = 0
List('c').isEmpty.??('X','+') // res2: Char = +
为了扩展@0__的答案(如果这是他/她的真名),您还可以使用元组一次分配给两个变量。
val (countA, countB) =
if (validItem) {
if (region.equalsIgnoreCase("US")) {
if (itemList > 0) (0,1) else (1,0)
} else {
(0,1)
}
} else {
(1,0)
}
这是一个老问题,我正在暂时解决当前的问题,所以我想我会留下一个基本的模式匹配解决方案。
val (countA, countB) =
(validItem, region.equalsIgnoreCase("US"), itemList > 0) match {
case (true, true, false) | (false, _, _) => (1, 0)
case _ => (0, 1)
}