如何编写三元条件运算符?

这个表达式在静态编程语言中的等价物是什么?

a ? b : c

这不是静态编程语言中的有效代码。

325975 次浏览

在静态编程语言中,if语句是表达式。所以下面的代码是等效的:

if (a) b else c

表达式和语句之间的区别在这里很重要。在Java /C#/JavaScript中,if形成一个语句,这意味着它不会解析为一个值。更具体地说,您不能将其分配给变量。

// Valid Kotlin, but invalid Java/C#/JavaScript
var v = if (a) b else c

如果你来自一种if是一个语句的语言,这可能看起来不自然,但这种感觉应该很快就会消退。

对于我自己,我使用以下扩展函数:

fun T?.or<T>(default: T): T = if (this == null) default else this
fun T?.or<T>(compute: () -> T): T = if (this == null) compute() else this

第一个将在对象等于null的情况下返回提供的默认值。第二个将在同一情况下评估lambda中提供的表达式。

用法:

1) e?.getMessage().or("unknown")
2) obj?.lastMessage?.timestamp.or { Date() }

就我个人而言,上面的代码比if构造内联更具可读性

看看文档

在静态编程语言中,if是一个表达式,即它返回一个值。因此 没有三元运算符(条件?然后:其他), 因为普通的如果在这个角色中工作得很好。

您可以定义自己的Boolean扩展函数,当Booleanfalse时返回null以提供类似于三元运算符的结构:

infix fun <T> Boolean.then(param: T): T? = if (this) param else null

这将使a ? b : c表达式转换为a then b ?: c,如下所示:

println(condition then "yes" ?: "no")

更新: 但是要做一些更Java的条件开关,你需要这样的东西

infix fun <T> Boolean.then(param: () -> T): T? = if (this) param() else null

println(condition then { "yes" } ?: "no") 注意lambda.它的内容计算应该推迟,直到我们确定conditiontrue

这个看起来很笨拙,这就是为什么对将三元运算符移植到静态编程语言Java要求很高的原因

当替换类C语言的开关运算符时。在最简单的形式中,它看起来像这样

when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}

在静态编程语言中,if是一个表达式,即它返回一个值。因此 没有三元运算符(condition ? then : else),因为 普通的如果在这个角色中工作得很好。手动源从这里

// Traditional usage
var max = a
if (a < b) max = b


// With else
var max: Int
if (a > b) {
max = a
} else {
max = b
}


// As expression
val max = if (a > b) a else b

正如Drew Noakes引用的那样,kotlin使用if语句作为表达式, 所以三元条件运算符不再是必需的,

但是使用扩展函数和中缀重载,您可以自己实现,这里是一个示例

infix fun <T> Boolean.then(value: T?) = TernaryExpression(this, value)


class TernaryExpression<out T>(val flag: Boolean, val truly: T?) {
infix fun <T> or(falsy: T?) = if (flag) truly else falsy
}

然后像这样使用它

val grade = 90
val clazz = (grade > 80) then "A" or "B"

静态编程语言中没有三元运算符。乍一看似乎有问题。但是认为我们可以使用内联if else语句来做到这一点,因为这是这里的表达式。简单地说,我们必须做-

var number = if(n>0) "Positive" else "Negetive"

在这里我们可以阻止太多我们需要的。像-

var number = if(n>0) "Positive" else if(n<0) "Negative" else "Zero"

所以这一行比三元运算符简单易读。当我们在Java中使用多个三元运算符时,这看起来很可怕。但是这里我们有一个清晰的语法。甚至我们也可以用多行写它。

一些角落案例在其他答案中没有提到。

由于外卖静态编程语言1.1中出现,三元运算符a ? b : c也可以这样表示:

b.takeIf { a } ?: c

在c为null的情况下,这变得更短:

b.takeIf { a }

使b懒惰评估的一般解决方法:

true.takeIf { a }?.let { b } ?: c

另请注意,世界上典型Java空检查,如value != null ? value : defaultValue,在理想的静态编程语言中仅翻译为value ?: defaultValue

类似的a != null ? b : c可以翻译成a?.let { b } ?: c


另请参阅KT-6938中的Boolean?.ifTrue提案,该提案应允许将a ? b : null表达式简化为a.ifTrue { b },而无需过早评估b

Java

int temp = a ? b : c;

等价于静态编程语言:

var temp = if (a) b else c

另一个有趣的方法是使用when

when(a) {
true -> b
false -> c
}

在一些更复杂的场景中可以非常方便。老实说,对我来说,它比if ... else ...更具可读性

kotlin中有无三元算子,因为if else块返回值。

你可以这样做: val max = if (a > b) a else b 而不是java的max = (a > b) ? b : c

我们也可以使用when构造,它也返回值:

val max = when(a > b) {
true -> a
false -> b
}

以下是kotlin留档链接:控制流:如果,当,为,而

另一种使用方法

val value : String = "Kotlin"


value ?: ""

这里kotlin本身检查null值,如果它为null,则传递空字符串值。

你可以用静态编程语言做很多事情

  1. 使用if

    if(a) b else c
    
  2. Using when

    when (a) {
    true -> print("value b")
    false -> print("value c")
    else -> {
    print("default return in any other case")
    }
    }
    
  3. Null Safety

    val a = b ?: c
    

太长别读

if (a) b else c

^是您可以用来代替静态编程语言语法不允许的三元运算符表达式a ? b : c


在静态编程语言中,许多控制语句,例如ifwhen,甚至try,都可以用作表达式。因此,这些语句可以具有可分配给变量的结果,可以从函数返回等。

语法上不需要三元运算符

由于静态编程语言的表达式,语言并不真正需要三元运算符

if (a) b else c

您可以使用它来代替三元运算符表达式a ? b : c

我认为前一个表达式更具可读性,因为每个人都知道ifelse做了什么,而如果你不熟悉语法,? :就相当不清楚了。

尽管如此,我不得不承认,我经常错过更方便的三元运算符。


其他替代品

在检查条件时,您可能还会看到静态编程语言中使用的when构造。这也是一种以另一种方式表达if-else级联的方式。以下对应于OTs示例。

when(a) {
true -> b
false -> c
}

扩展

正如其他答案中的许多好例子(静态编程语言三元条件运算符)所示,扩展也可以帮助解决您的用例。

使用以下中缀函数,我可以覆盖许多常见的用例,就像在Python中一样:

class TestKotlinTernaryConditionalOperator {


@Test
fun testAndOrInfixFunctions() {
Assertions.assertThat(true and "yes" or "no").isEqualTo("yes")
Assertions.assertThat(false and "yes" or "no").isEqualTo("no")


Assertions.assertThat("A" and "yes" or "no").isEqualTo("yes")
Assertions.assertThat("" and "yes" or "no").isEqualTo("no")


Assertions.assertThat(1 and "yes" or "no").isEqualTo("yes")
Assertions.assertThat(0 and "yes" or "no").isEqualTo("no")


Assertions.assertThat(Date() and "yes" or "no").isEqualTo("yes")
@Suppress("CAST_NEVER_SUCCEEDS")
Assertions.assertThat(null as Date? and "yes" or "no").isEqualTo("no")
}
}


infix fun <E> Boolean?.and(other: E?): E? = if (this == true) other else null
infix fun <E> CharSequence?.and(other: E?): E? = if (!(this ?: "").isEmpty()) other else null
infix fun <E> Number?.and(other: E?): E? = if (this?.toInt() ?: 0 != 0) other else null
infix fun <E> Any?.and(other: E?): E? = if (this != null) other else null
infix fun <E> E?.or(other: E?): E? = this ?: other

您可以在静态编程语言中为此使用if表达式。在静态编程语言中,if是具有结果值的表达式。因此,在静态编程语言中,我们可以编写

fun max(a: Int, b: Int) = if (a > b) a else b

在Java,我们可以用更大的代码实现相同的目标

int max(int a, int b) {
return a > b ? a : b
}

当使用应用()时,让我们在处理三元操作时看起来非常方便,因为它更优雅,给你空间

val columns: List<String> = ...
val band = Band().apply {
name = columns[0]
album = columns[1]
year = columns[2].takeIf { it.isNotEmpty() }?.let { it.toInt() } ?: 0
}

静态编程语言中没有三元操作,但有一些有趣的方法可以解决这个问题。正如其他人指出的,直接翻译成静态编程语言如下所示:

val x = if (condition) result1 else result2

但是,就我个人而言,我认为这可能会变得有点混乱和难以阅读。库中内置了一些其他选项。你可以在elvis运算符中使用外卖if{}:

val x = result1.takeIf { condition } ?: result2

那里发生的事情是,bexif{}命令返回您的结果1或null,而elvis运算符处理null选项。还有一些额外的选项,例如:

val x = result1.takeUnless { condition } ?: result2

语言很清楚,你知道这是在做什么。

如果这是一个常用的条件,你也可以做一些有趣的事情,比如使用内联扩展方法。例如,假设我们想以Int跟踪游戏分数,如果给定条件不满足,我们希望始终返回0:

inline fun Int.zeroIfFalse(func: () -> Boolean) : Int = if (!func.invoke()) 0 else this

好吧,这看起来很丑陋。但是考虑一下它在使用时的样子:

var score = 0
val twoPointer = 2
val threePointer = 3


score += twoPointer.zeroIfFalse { scoreCondition }
score += threePointer.zeroIfFalse { scoreCondition }

如您所见,静态编程语言在您选择如何表达代码方面提供了很大的灵活性。我的示例有无数种变体,可能还有我还没有发现的方法。我希望这能有所帮助!

静态编程语言中没有三元运算符,最封闭的是下面两种情况,

  • 如果其他作为表达式语句

val a = true if(a) print("A is true") else print("A is false")

  • 埃尔维斯算子

如果?:左侧的表达式不为空,则elvis运算符 返回它,否则它将表达式返回到右侧。注意 仅当左侧表达式的值为0时,才计算右侧表达式 边为空。

 val name = node.getName() ?: throw IllegalArgumentException("name expected")

参考文档

示例:var能量:Int=data?. get(位置)?. Energy?. toInt()?: 0

在kotlin中,如果你使用的是?:,它的工作方式就像如果语句返回null,那么?: 0它将取0或你在这一边写的任何东西。

为什么要使用这样的东西:

when(a) {
true -> b
false -> b
}

当你实际上可以使用这样的东西时(a在这种情况下是布尔值):

when {
a -> b
else -> b
}

您可以使用var a= if (a) b else c代替三元运算符。

Kotlin的另一个好概念是埃尔维斯运算符。你不需要每次都检查null。

val l = b?.length ?: -1

如果b不为空,这将返回长度,否则它执行右侧语句。

如果条件为假,则为“错误”,否则为“某个字符串”

在编写三元条件运算符之前,让我们考虑以下原型:

if (!answer.isSuccessful()) {
result = "wrong"
} else {
result = answer.body().string()
}


return result


解决方案

您可以在静态编程语言的if-expression中使用!(逻辑非)运算符:

return if (!answer.isSuccessful()) "wrong" else answer.body().string()

如果你翻转if-expression(不带!运算符的表达式)会更好:

return if (answer.isSuccessful()) answer.body().string() else "wrong"

Kotlin的埃尔维斯操作员?:可以做得更好:

return answer.body()?.string() ?: "wrong"

此外,对相应的Answer类使用Extension function

fun Answer.bodyOrNull(): Body? = if (isSuccessful()) body() else null

Extension function中,由于Elvis operator,您可以减少代码:

return answer.bodyOrNull()?.string() ?: "wrong"

或者只使用when条件表达式:

when (!answer.isSuccessful()) {
parseInt(str) -> result = "wrong"
else -> result = answer.body().string()
}

请记住三元算子埃尔维斯算子静态编程语言中具有不同的含义,这与许多流行语言不同。执行expression? value1: value2会给静态编程语言编译器带来不好的词,与官方文档中提到的静态编程语言中没有三元运算符不同。原因是如果,何时和尝试捕获语句本身返回值。

因此,执行expression? value1: value2可以替换为

val max=if(a>b) print(选择一个) 否则 print("选择b")

静态编程语言拥有的埃尔维斯算子仅适用于可为空变量的情况,例如:

如果我做类似value3 = value1 ?: value2的事情,那么如果value e1null,那么value e2将被返回,否则value e1将被返回。

这些答案可以获得更清晰的理解。

Java等价于三元算子

a ? b : c

是一个简单的IF在静态编程语言中的一行

if(a) b else c

没有三元运算符(条件?然后:其他),因为 普通的如果在这个角色中工作得很好。

https://kotlinlang.org/docs/reference/control-flow.html#if-expression


Null比较的特殊情况

您可以使用埃尔维斯算子

if ( a != null ) a else b
// equivalent to
a ?: b

如果您不使用标准符号,您也可以使用中缀创建/模拟它,如下所示:

创建一个类来保存你的目标和结果:

data class Ternary<T>(val target: T, val result: Boolean)

创建一些中缀函数来模拟三元操作

infix fun <T> Boolean.then(target: T): Ternary<T> {
return Ternary(target, this)
}


infix fun <T> Ternary<T>.or(target: T): T {
return if (this.result) this.target else target
}

然后你可以像这样使用它:

val collection: List<Int> = mutableListOf(1, 2, 3, 4)


var exampleOne = collection.isEmpty() then "yes" or "no"
var exampleTwo = (collection.isNotEmpty() && collection.contains(2)) then "yes" or "no"
var exampleThree = collection.contains(1) then "yes" or "no"

在静态编程语言中,您可以像这样使用三元运算:val x = if(a) "add b" else "add c"

funmax(x: Int, y: Int): String=if(x>y)"max=$x"or"max=$y"

内联函数

静态编程语言没有三元运算符。您可以使用常规的if表达式,如下所示:

if (condition) exp1 else exp2

此外,静态编程语言中的if不是语句而是表达式(即它的计算结果为一个值),在if分支(或elseelse if的主体)的主体中有多个语句的情况下,块的最后一行是该分支的值。例如:

if (a>b) {
println("a is greater than b")
a // value of this if
} else {
println("b is greater than a")
b // value of else
}

你可以这样做:

val ans = (exp1 == exp2) then "yes" ?: "no"

通过使用此扩展:

infix fun<T> Boolean.then(first: T): T? = if (this) first else null

注意:不要将上面的中缀函数修改为接受first: T?,否则表达式逻辑上会出错。例如:如果你将其修改为接受可空的first: T?,那么val ans = (true == true) then null ?: "abcd"ans将是"abcd",这是不正确的。

在Java,if是一个语句,但在静态编程语言中if是一个表达式。它被称为表达式是因为它比较a和b的值并返回最大值。因此,在静态编程语言中没有三元运算符(a>b)? a: b,因为它被if表达式替换。

这里的其他答案,例如takeIf假设类似于x = (a != null) ? a : cx = (a != null) ? a.method() : c,但实际上并不等同于x = a ? b : c

要实现具有空安全检查(即x = (a != null) ? b : c)的三元运算符的真正等价物,您可以使用let而不是takeIf,即let

val x=a?. let{b}?: c

其中b可能是也可能不是调用a的方法。