Kotlin三元条件算子

Dre*_*kes 398 ternary-operator kotlin

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

a ? b : c
Run Code Online (Sandbox Code Playgroud)

这不是Kotlin中的有效代码.

Dre*_*kes 548

在Kotlin中,if陈述是表达式.所以下面的代码是等价的:

if (a) b else c
Run Code Online (Sandbox Code Playgroud)

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

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

如果你来自if一种声明的语言,这可能看起来不自然,但这种感觉很快就会消退.

  • 另外你可以使用`when`. (52认同)
  • 特别提及`var v = a ?: b`。这与 `var v = if(a != null) a else b` 相同 (9认同)
  • 只是要添加,如果它是一个布尔表达式,你甚至可以使用`x = a == b` (5认同)
  • @AdeelAnsari 不,它不是在纠正。情况更糟。比较这个。`b + if (a) c else d` vs. `b + (c if (a) else d)` 后者需要额外的括号。因为 `c` 没有被条件和 `else` 包围。 (5认同)
  • 这里是关于这个话题的一些讨论。https://discuss.kotlinlang.org/t/ternary-operator/2116/141 (4认同)
  • 拥有 Elvis 运营商,而不是三元运营商,简直是愚蠢至极。然而,这可以通过调整 Pythonic 的三元方式来稍微纠正,`b if (a) else c`,而不是 `if (a) b else c`。顺便说一句,我也不喜欢那个。 (2认同)
  • Pythonic 方式更接近英语,但远没有那么数学化。它需要额外的语法结构。目前,每个“if”语句或“when”语句实际上都是一个“表达式”,因此“它只是作为三元运算符起作用”。然而,“b if (a) else c”并不只是按原样工作。如果我们删除“if (a) b else c”并添加“b if (a) else c”,则与“if”语句实际上是一个表达式的事实相冲突。它还破坏了与“when”的一致性。 (2认同)

dev*_*ant 63

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

infix fun <T> Boolean.then(param: T): T? = if (this) param else null
Run Code Online (Sandbox Code Playgroud)

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

println(condition then "yes" ?: "no")
Run Code Online (Sandbox Code Playgroud)

更新: 但是要做一些类似Java的条件切换,你需要这样的东西

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

println(condition then { "yes" } ?: "no") 关注lambda.其内容计算应推迟到我们确定conditiontrue

这个看起来很笨拙,这就是为什么存在将Java三元运算符移植到Kotlin中的高要求

  • `infix inline fun&lt;T&gt; Boolean.then(param: ()-&gt;T):T? = if(this) param() else null` (3认同)
  • 使用&lt;T:Any&gt;,否则将无法正常工作:`true then {null}?:“ not-null”` (3认同)
  • 顺便说一句,这里的“?:”运算符是“elvis-operator”:https://kotlinlang.org/docs/reference/null-safety.html#elvis-operator (2认同)

s1m*_*nw1 43

TL; DR

if (a) b else c是你可以使用而不是Java表达式a ? b : c.


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

从语法上讲,不需要三元运算符

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

if (a) b else c是你可以使用而不是Java表达式a ? b : c.

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


其他替代品

什么时候

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

when(a) {
    true -> b
    false -> c
}
Run Code Online (Sandbox Code Playgroud)

扩展

在其他答案中,尽可能多的好例子(Kotlin三元条件运算符),扩展也可以是一种方法.


ruX*_*ruX 35

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

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
Run Code Online (Sandbox Code Playgroud)

如果对象等于null,则第一个将返回提供的默认值.其次将评估在同一情况下在lambda中提供的表达式.

用法:

1) e?.getMessage().or("unknown")
2) obj?.lastMessage?.timestamp.or { Date() }
Run Code Online (Sandbox Code Playgroud)

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

  • 它与问题无关,但为什么不使用__?:_ _,_elvis operator_?第一个函数将替换为`e.getMessage()?:"unknown"`.第二个可以表示为`obj?.lastMessage?.timestamp?:{Date()}()` (32认同)
  • @ruX elvis运营商专门为此而且您的使用相当不寻常. (14认同)
  • 虽然?:很好,但是我们不要走太远的Perl. (6认同)
  • @hotkey 没有特殊用途。从我的角度来看,它在链式操作中看起来更一致,视觉上的噪音更小,因为您不应该将构造包裹在括号中 (2认同)

小智 29

没有三元运算符在科特林,作为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
}
Run Code Online (Sandbox Code Playgroud)

以下是kotlin文档的链接:控制流程:if,when,for,while


Kri*_*ofe 27

在Kotlin中,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
Run Code Online (Sandbox Code Playgroud)


Vad*_*zim 24

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

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

b.takeIf { a } ?: c
Run Code Online (Sandbox Code Playgroud)

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

b.takeIf { a }
Run Code Online (Sandbox Code Playgroud)

还要注意,Java世界中的典型null检查就像value != null ? value : defaultValue在ideomatic Kotlin中翻译一样value ?: defaultValue.

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

  • `b.takeIf {a}?:c`比`if(a)b else c`更短,更可读?Terneray运算符肯定是Kotlin中缺少的一个功能,因为变量名称和条件可能会很长并且会让你分裂出坏的行 (6认同)
  • 还应该注意的是,`takeIf` 总是评估真实情况(这里是 `a`)。如果`a` 恰好为false,那么该表达式不仅会被无用地计算,而且你不能从智能转换中受益,如`if (a is Int) { a + 3 }`。 (3认同)
  • 我写错了,应该是“总是评估真实情况(这里是`b`)”。但即使是 `{ a }`,虽然很懒惰,但_必须_评估以确定表达式的结果。 (3认同)
  • @TheOperator,错了。`{ a }` 是一个延迟计算的 lambda。 (2认同)
  • `b.takeIf { a }` 在技术上等同于 `b = a` (2认同)

Li *_*ing 23

看看文档:

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


Ray*_*non 18

Java相当于三元运算符

a ? b : c
Run Code Online (Sandbox Code Playgroud)

是一行在Kotlin中的简单IF

if(a) b else c
Run Code Online (Sandbox Code Playgroud)

没有三元运算符(条件?then:else),因为普通if在此角色下工作正常。

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


空比较的特殊情况

您可以使用猫王运算符

if ( a != null ) a else b
// equivalent to
a ?: b
Run Code Online (Sandbox Code Playgroud)


小智 14

Java的

int temp = a ? b : c;
Run Code Online (Sandbox Code Playgroud)

相当于Kotlin:

var temp = if (a) b else c
Run Code Online (Sandbox Code Playgroud)


小智 12

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

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> {
        print("x is neither 1 nor 2")
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,但是你展示的例子有`when`作为陈述,而不是表达.与三元条件表达式进行更相关的比较将使每个分支返回一个值,以便整个when表达式求值为一个值(如三元条件所发生的那样). (3认同)

kri*_*han 12

Kotlin 没有三元运算符。您可以使用正则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
}
Run Code Online (Sandbox Code Playgroud)


HM *_*yem 10

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

var number = if(n>0) "Positive" else "Negetive"
Run Code Online (Sandbox Code Playgroud)

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

var number = if(n>0) "Positive" else if(n<0) "Negative" else "Zero"
Run Code Online (Sandbox Code Playgroud)

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


And*_*eek 8

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

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

val l = b?.length ?: -1
Run Code Online (Sandbox Code Playgroud)

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


ARG*_*Geo 8

任务

让我们考虑以下示例:

if (!answer.isSuccessful()) {
    result = "wrong"
} else {
    result = answer.body().string()
}
return result
Run Code Online (Sandbox Code Playgroud)

我们在Kotlin中需要以下等效项:

返回(!answer.isSuccessful()) ? “错误”的 : answer.body()。string()

在此处输入图片说明

解决方案

1.A。您可以if-expression在Kotlin中使用:

return if (!answer.isSuccessful()) "wrong" else answer.body().string()
Run Code Online (Sandbox Code Playgroud)

1.B。翻转此按钮会更好if-expression(让我们不用not):

return if (answer.isSuccessful()) answer.body().string() else "wrong"
Run Code Online (Sandbox Code Playgroud)

2。Kotlin的Elvis操作员?:可以做得更好:

return answer.body()?.string() ?: "wrong"
Run Code Online (Sandbox Code Playgroud)

3。或将Extension function用作相应的Answer类:

fun Answer.bodyOrNull(): Body? = if (isSuccessful()) body() else null
Run Code Online (Sandbox Code Playgroud)

4。使用,Extension function您可以减少代码,这要归功于Elvis operator

return answer.bodyOrNull()?.string() ?: "wrong"
Run Code Online (Sandbox Code Playgroud)

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

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

希望这可以帮助。


Min*_*ami 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
}
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它

val grade = 90
val clazz = (grade > 80) then "A" or "B"
Run Code Online (Sandbox Code Playgroud)

  • 但是添加 &lt;T&gt; 可以使它工作: (grade &gt; 80) then null or "B" (2认同)

Raj*_*iya 7

你可以在Kotlin做很多事

  1. 使用if

    if(a) b else c
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用时

    when (a) { 
        true -> print("value b") 
        false -> print("value c") 
        else -> {  
            print("default return in any other case") 
        } 
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 空安全

    val a = b ?: c
    
    Run Code Online (Sandbox Code Playgroud)


Eud*_*ras 7

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

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

data class Ternary<T>(val target: T, val result: Boolean)
Run Code Online (Sandbox Code Playgroud)

创建一些中缀函数来模拟三元运算

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
}
Run Code Online (Sandbox Code Playgroud)

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

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"
Run Code Online (Sandbox Code Playgroud)


Grz*_*rek 6

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

when(a) {
  true -> b
  false -> b
}
Run Code Online (Sandbox Code Playgroud)

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


Nee*_*ani 6

请记住,与许多流行语言不同,三元运算符猫王运算符Kotlin 中具有不同的含义。这样做expression? value1: value2会让Kotlin编译器给你不好的词,这与任何其他语言不同,因为Kotlin没有官方文档中提到的三元运算符。原因是if、when 和 try-catch语句本身返回值。

所以,doingexpression? value1: value2可以替换为

val max = if (a > b) print("选择a") else print("选择b")

Elvis操作符科特林了,只能在可空变量前的情况:

如果我执行类似的操作,value3 = value1 ?: value2则如果value1null,则将返回value2,否则将返回value1

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


小智 5

Kotlin中没有三元运算,但是有一些有趣的方法可以解决此问题。正如其他人指出的那样,直接翻译成Kotlin会像这样:

val x = if (condition) result1 else result2
Run Code Online (Sandbox Code Playgroud)

但是,就我个人而言,我认为这可能会有些混乱并且难以阅读。库中还内置了其他一些选项。您可以将takeIf {}与Elvis运算符配合使用:

val x = result1.takeIf { condition } ?: result2
Run Code Online (Sandbox Code Playgroud)

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

val x = result1.takeUnless { condition } ?: result2
Run Code Online (Sandbox Code Playgroud)

语言很清楚,您知道该怎么做。

如果这是一种常用条件,您还可以做一些有趣的事情,例如使用内联扩展方法。假设我们想以例如Int的形式跟踪游戏分数,并且如果不满足给定条件,我们想始终返回0:

inline fun Int.zeroIfFalse(func: () -> Boolean) : Int = if (!func.invoke()) 0 else this     
Run Code Online (Sandbox Code Playgroud)

好吧,这看起来很丑。但是请考虑使用它时的外观:

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

score += twoPointer.zeroIfFalse { scoreCondition } 
score += threePointer.zeroIfFalse { scoreCondition } 
Run Code Online (Sandbox Code Playgroud)

如您所见,Kotlin在选择表达代码方面提供了很大的灵活性。我的示例有无数种变化,甚至可能还没有发现。我希望这有帮助!


小智 5

你可以这样做:

val ans = (exp1 == exp2) then "yes" ?: "no"
Run Code Online (Sandbox Code Playgroud)

通过使用这个扩展:

infix fun<T> Boolean.then(first: T): T? = if (this) first else null
Run Code Online (Sandbox Code Playgroud)

PS:上面的中缀函数不要修改为 accept first: T?,表达式会逻辑不正确。例如:如果您修改它以接受 nullable first: T?,则val ans = (true == true) then null ?: "abcd",ans将是"abcd",这是不正确的。