Kotlin三元条件算子

问题描述 投票:346回答:27

Kotlin中这个表达的等价物是什么?

a ? b : c

这不是Kotlin中的有效代码。

ternary-operator kotlin
27个回答
515
投票

在Kotlin中,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是一个声明,这可能看起来不自然,但这种感觉很快就会消退。


12
投票

当替换类C语言的switch操作符时。在最简单的形式,它看起来像这样

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

10
投票

Kotlin没有三元运营商。乍一看似乎有问题。但是我认为我们可以使用inline if else语句来实现它,因为这是表达式。我们只需做 -

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

在这里我们可以阻止我们需要的多少。喜欢-

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

所以这条线比三元运算符简单易读。当我们在java中使用多个三元运算符时,它似乎很糟糕。但在这里我们有一个清晰的语法。即使我们也可以用多行编写它。


8
投票

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

kotlin的另一个好概念是猫王操作员。您不需要每次都检查null。

val l = b?.length ?: -1

如果b不为null,则返回length,否则执行右侧语句。


7
投票

正如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"

7
投票

你可以在Kotlin做很多事

  1. 使用if if(a) b else c
  2. 使用时 when (a) { true -> print("value b") false -> print("value c") else -> { print("default return in any other case") } }
  3. 空安全 val a = b ?: c

7
投票

任务:

让我们考虑以下示例:

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

我们在Kotlin中需要以下等价物:

return(!answer.isSuccessful())?“wrong”: answer.body()。string()

enter image description here

解决方案:

表1.A你可以在Kotlin中使用if-expression

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

1.B.如果你翻转这个if-expression可能会好得多(让我们在没有not的情况下这样做):

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

2. Kotlin的Elvis运营商?:可以做得更好:

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

3.或者使用Extension function作为相应的Answer类:

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

4.使用Extension function,你可以通过Elvis operator减少代码:

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

5.或者只使用when运算符:

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

希望这可以帮助。


7
投票

Java相当于三元运算符

a ? b : c

在Kotlin中是一个简单的IF

if(a) b else c

没有三元运算符(条件?则:else),因为普通的if在这个角色中工作正常。

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


Null比较的特例

你可以使用Elvis operator

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

6
投票

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

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

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


5
投票

Kotlin没有三元手术,但有一些有趣的方法可以解决这个问题。正如其他人所指出的那样,直接翻译成Kotlin会如下所示:

val x = if (condition) result1 else result2

但是,就个人而言,我认为可能会有点混乱,难以阅读。库中还内置了一些其他选项。你可以使用带有elvis运算符的takeIf {}:

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

发生的事情是takeIf {}命令返回result1或null,而elvis运算符处理null选项。还有一些其他选项,例如:takeUnless {}

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 } 

如您所见,Kotlin为您选择表达代码提供了很大的灵活性。我的例子有无数种变化,可能还有我尚未发现的方法。我希望这有帮助!


4
投票

记住三元运算符和Elvis运算符在Kotlin中具有与许多流行语言不同的含义。做expression? value1: value2会给你Kotlin编译器的坏话,不像任何其他语言,因为在official docs中提到的Kotlin中没有三元运算符。原因是if,when和try-catch语句本身返回值。

所以,做expression? value1: value2可以取代

val max = if(a> b)print(“选择一个”)否则打印(“选择b”)

Kotlin拥有的Elvis运算符仅适用于可空变量的情况:

如果我执行类似value3 = value1 ?: value2的操作,那么如果value1为null,则返回value2,否则返回value1。

these answers可以获得更清晰的理解。


58
投票

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

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

这个看起来很笨拙,that is why there is high demanded request exist to port Java ternary operator into Kotlin


3
投票

您可以在Kotlin中使用if表达式。在Kotlin中,if是一个带有结果值的表达式。所以在Kotlin我们可以写

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

在Java中,我们可以实现相同但更大的代码

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

1
投票

另一种简短的使用方法

val value : String = "Kotlin"

value ?: ""

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


1
投票

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

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

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

when {
  a -> b
  else -> b
}

1
投票

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

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

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"

0
投票

使用以下中缀函数,我可以涵盖许多常见用例,几乎与在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

0
投票

Kotlin没有三元运营商,最封闭的是以下两种情况,

  • 如果是else作为表达式语句

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

  • 猫王经营者

如果?:左边的表达式不为null,则elvis运算符返回它,否则返回右边的表达式。请注意,仅当左侧为空时才评估右侧表达式。

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

Reference docs


0
投票

例如:var energy:Int = data?.get(position)?. energy?.toInt()?:0

在kotlin中,如果你正在使用?:它会起作用,如果语句将返回null然后?:0它将需要0或任何你写的这边。


0
投票

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

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

0
投票

经过对其他想法的一些研究,我得出了以下三元运算符:

infix fun <T : Any> Boolean.yes(trueValue: T): T? = if (this) trueValue else null
infix fun <T : Any> T?.no(falseValue: T): T = this ?: falseValue

示例(运行here):

fun main() {
    run {
        val cond = true
        val result = cond yes "True!" no "False!"
        println("ternary test($cond): $result")
    }
    run {
        val cond = false
        val result = cond yes "True!" no "False!"
        println("ternary test($cond): $result")
    }
}

此版本流畅,不会与null合并运算符冲突。


40
投票

TL;DR

if (a) b else c是你可以用来代替Java表达式a ? b : c


在Kotlin中,许多控制语句,包括ifwhen甚至try都可以用作表达式。这意味着那些可以具有可以分配给变量的结果,从函数返回等。

Syntactically, no need for ternary operator

因此,Kotlin不需要三元运算符。

if (a) b else c是你可以用来代替Java表达式a ? b : c

我认为后者的可读性较差,因为每个人都知道ifelse的作用,而? :如果你不熟悉语法则相当不方便。虽然我不得不承认我经常想念更方便的三元运算符。


其他替代品

什么时候

在Kotlin中检查条件时,您可能还会看到很多when构造。它也是一种以另一种方式表达if-else级联的方法。以下对应于您的示例。

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

扩展

正如其他答案中的许多好例子(Kotlin Ternary Conditional Operator)所示,扩展也可以是一种方法。


34
投票

对于我自己,我使用以下扩展功能:

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构造内联更具可读性


29
投票

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文档的链接:Control Flow: if, when, for, while


27
投票

在Kotlin中,if是一个表达式,即它返回一个值。因此没有三元运算符(condition ? then : else),因为普通如果在这个角色中工作正常。 manual source from here

// 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

23
投票

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

自从在takeIf出现Kotlin 1.1以来,三元运算符a ? b : c也可以这样表达:

b.takeIf { a } ?: c

如果c是null,这变得更短:

b.takeIf { a }

另请注意,典型的Java世界空检查(如value != null ? value : defaultValue)在ideomatic Kotlin中转换为value ?: defaultValue

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


23
投票

看看docs

在Kotlin中,if是一个表达式,即它返回一个值。因此没有三元运算符(条件?则:else),因为普通的if在这个角色中工作正常。


14
投票

Java的

int temp = a ? b : c;

相当于Kotlin:

var temp = if (a) b else c
© www.soinside.com 2019 - 2024. All rights reserved.