코 틀린 3 차 조건부 연산자


답변:


617

코 틀린에서 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성명서가 있는 언어에서 온다면 이것은 부 자연스럽게 보일지 모르지만 그 느낌은 곧 사라질 것입니다.


57
또한을 사용할 수 있습니다 when.
bashor

5
부울 표현식 인 경우 다음과 같이 추가 할 수도 있습니다.x = a==b
gnomeria

2
@ MikeRylander 나는 이것을 명시 적으로 만들기 위해 대답을 확장했습니다. 이것을 지적 해 주셔서 감사합니다.
Drew Noakes

1
@AdeelAnsari 아니요, 정류하지 않습니다. 더 나쁘다. 이것을 비교하십시오. b + if (a) c else db + (c if (a) else d)후자는 추가 괄호가 필요합니다. c조건으로 묶이지 않기 때문 입니다 else.
Naetmul

1
이 주제에 대한 약간의 토론이 있습니다. 토론 .kotlinlang.org
F. Norbert

70

당신은 당신의 자신의 정의 할 수 있습니다 Boolean반환하는 확장 기능을 null(가) Boolean입니다이 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") 람다에주의하십시오. 콘텐츠 계산 conditiontrue

이것은 서투른 것처럼 보이 므로 Java 삼항 연산자를 Kotlin으로 포팅하는 데 필요한 요구가 높은 이유입니다.


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

3
사용 <T : 모든>, 그렇지 않으면 그 잘못 작동합니다 :true then { null } ?: "not-null"
유진 페트 렌코

BTW, ?:운영자는 elvis-operator다음과 같습니다. kotlinlang.org/docs/reference/null-safety.html#elvis-operator
Eric Wang

64

TL; DR

if (a) b else c

삼항 연산자 식 대신 사용할 수 있습니다 a ? b : c.


코 틀린, 많은 제어문을 포함 if, when또는 심지어 try로 사용할 수 있습니다 표현 . 이것은 변수에 할당되고 함수 등에서 반환되는 결과를 가질 수 있음을 의미합니다.

문법적으로 삼항 연산자가 필요하지 않습니다.

Kotlin의 표현의 결과로 언어 에는 실제로 삼항 연산자가 필요하지 않습니다 .

if (a) b else c

삼항 연산자 식 대신 사용할 수 있습니다 a ? b : c.

아이디어는 모든 사람들이 무엇을 알고 있기 때문에 이전 표현이 더 읽기 쉽다고 생각 ifelse하지만 ? :이미 구문에 익숙하지 않으면 다소 명확하지 않습니다.

그럼에도 불구하고 나는 종종 더 편리한 삼항 연산자를 그리워 한다는 것을 인정해야 합니다.


다른 대안들

언제

when조건을 확인할 때 Kotlin에서 사용 된 구문 을 볼 수도 있습니다 . 또 다른 방법으로 if-else 캐스케이드를 표현하는 방법이기도합니다. 다음은 OTs 예에 해당합니다.

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

확장

다른 답변에서 많은 좋은 예 ( Kotlin Ternary Conditional Operator )가 보여 주듯이 확장은 사용 사례 해결에 도움이 될 수 있습니다.


36

나 자신을 위해 다음 확장 기능을 사용합니다.

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

첫 번째는 object가 null과 같은 경우 제공된 기본값을 반환합니다. 두 번째는 같은 경우에 람다로 제공된 표현을 평가합니다.

용법:

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

개인적으로 if건설 인라인 보다 더 읽기 쉬운 코드


34
이 질문에 그와 관련이없는,하지만 사용하지 왜 ? 는이 연산자를 엘비스 ? 첫 번째 기능은로 대체됩니다 e.getMessage() ?: "unknown". 두 번째는 다음과 같이 표현 될 수 있습니다.obj?.lastMessage?.timestamp ?: { Date() }()
핫키

1
@hotkey에는 특별한 목적이 없습니다. 내 관점에서 그건 더 일관하고 괄호 안에 건설을 감싸 안로서 체인 운영에 시각적으로 덜 시끄러운 외모
RUX

14
@ruX elvis 연산자는 특별히이 용도로 사용되며 다소 드물게 사용됩니다.
Jayson Minard

6
? :는 괜찮지 만 Perl로가는 길을 너무 멀리 가지 마십시오.
Richard Haven


28

블록이 값을 반환하기 때문에 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 문서에 대한 링크는 다음과 같습니다. 제어 흐름 : if, when, for, while


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

26

다른 답변에 언급되지 않은 일부 코너 사례.

외관 때문에 takeIf 에서 코 틀린 1.1 삼원 연산자 a ? b : c도 다음과 같이 표현 될 수있다 :

b.takeIf { a } ?: c

c가 null다음 과 같은 경우에 더 짧아집니다 .

b.takeIf { a }

같은 또한 자바 세계 널 (null) 검사에서 그 전형적인주의 value != null ? value : defaultValue단지에 ideomatic 코 틀린에 번역 value ?: defaultValue.

유사는 a != null ? b : c에 번역 할 수 있습니다 a?.let { b } ?: c.


6
b.takeIf { a } ?: c보다 짧고 읽기 쉬운 방법은 if (a) b else c무엇입니까? 변수 이름과 조건이 길어질 수 있고 나쁜 줄을 나눌 수 있기 때문에 Terneray 연산자는 확실히 Kotlin에서 누락 된 기능입니다.
Javad Sadeqzadeh

1
또한 takeIf항상 실제 사례 (여기 a)를 평가 한다는 점에 유의해야합니다 . a허위 일 경우 해당 표현을 쓸모 없게 계산할 수있을뿐만 아니라 , 스마트 캐스트에서 혜택을 누릴 수 없습니다 if (a is Int) { a + 3 }.
TheOperator

@TheOperator, 잘못되었습니다. { a }게으르게 평가 된 람다입니다.
Vadzim

1
"항상 실제 사례를 평가합니다 b" (여기서는 ) 여야합니다 . 그러나 { a }게으른 상태 에서도 식의 결과를 결정하기 위해 평가 해야합니다 .
오퍼레이터

24

문서를 살펴보십시오 .

Kotlin에서 if는 표현식입니다. 즉, 값을 반환합니다. 따라서 평범한 경우이 역할에서 잘 작동하기 때문에 삼항 연산자 (조건? then : else)는 없습니다.


13

자바

int temp = a ? b : c;

코 틀린에 해당 :

var temp = if (a) b else c

12

임무 :

다음 예제를 살펴 보겠습니다.

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

Kotlin에는 다음과 같은 것이 필요합니다.

return (! answer.isSuccessful ()) ? "잘못된" : answer.body (). string ()


해결책 :

1.A . if-expressionKotlin에서 사용할 수 있습니다 :

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()
}

도움이 되었기를 바랍니다.


11

C와 같은 언어의 스위치 연산자를 대체 할 때 가장 간단한 형태는 다음과 같습니다

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

3
사실이지만, 당신이 보여주는 예 when는 표현이 아닌 진술로되어 있습니다. 삼항 조건식과 더 관련있는 비교는 각 분기가 값을 반환하도록하여식이 값으로 평가 될 때 전체가 삼항 조건부에서 발생하는 것처럼 전체 값을 반환하도록하는 것입니다.
Drew Noakes

9

코 틀린에는 삼항 연산자가 없습니다. 언뜻보기에는 문제가있는 것 같습니다. 그러나 여기에 표현이 있기 때문에 다른 문장이라면 인라인으로 할 수 있다고 생각하십시오. 간단히 우리는해야합니다-

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

여기서 필요한만큼 블록을 차단할 수 있습니다. 처럼-

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

따라서이 줄은 삼항 연산자보다 간단하고 읽기 쉽습니다. 우리가 자바에서 둘 이상의 삼항 연산자를 사용할 때 그것은 끔찍한 것 같습니다. 그러나 여기에는 명확한 구문이 있습니다. 심지어 여러 줄로도 쓸 수 있습니다.


9

var a= if (a) b else c삼항 연산자 대신 사용할 수 있습니다 .

kotlin의 또 다른 좋은 개념은 Elvis operator입니다. 매번 null을 확인할 필요는 없습니다.

val l = b?.length ?: -1

b가 null이 아닌 경우 길이를 반환하고 그렇지 않으면 오른쪽 문을 실행합니다.


7

Drew Noakes가 인용했듯이 kotlin은 if 문을 표현식으로 사용하므로 더 이상 Ternary Conditional Operator가 필요하지 않습니다.

확장 기능과 오버로드 오버로드를 사용하면 직접 구현할 수 있습니다. 여기에 예가 있습니다.

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"

? = 정말 다른 falsy (플래그)의 경우 : 어쩌면 <T> 더 나은 중위 재미 나 (? T falsy) 제거
솔로

1
그러나 추가 <T> 작동 할 수 있습니다 : (급> 80)는 null 또는 "B"
솔로

이것은 정말 멋지다. 나는 그것을 사용할 것이다. 큰 문제는 아니지만 비용이 들지 않는 추상화는 아닙니다.
Adam

6

또 다른 흥미로운 접근법은 다음을 사용하는 것입니다 when.

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

좀 더 복잡한 시나리오에서 매우 유용 할 수 있습니다. 그리고 솔직히, 그것은 나보다 더 읽기 쉽습니다.if ... else ...


6

코 틀린에서 여러 가지 방법으로 할 수 있습니다

  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

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은 코드 표현 방식에 많은 유연성을 제공합니다. 내 예제에는 수많은 변형이 있으며 아마도 아직까지도 발견하지 못한 방법이 있습니다. 이게 도움이 되길 바란다!


takeIf내가 가장 좋아하는 옵션은 정말 우아합니다.
Javier Mendonça

4

기억 삼항 연산자엘비스 운영자 에 보류 별도의 의미 코 틀린를 많은 대중적인 언어와는 달리. 수행 expression? value1: value2에 의해 당신에게 나쁜 말을 줄 것 코 틀린에 없기 때문에 다른 언어와는 달리, 컴파일러 코 틀린에는 삼항 연산자 에 언급 된 공식 문서가 . 그 이유는 if, when 및 try-catch 문 자체가 값을 반환하기 때문입니다.

따라서 수행 expression? value1: value2은 다음으로 대체 될 수 있습니다.

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

엘비스 운영자 것을 코 틀린이 있습니다 만 널 (NULL) 변수 전직의 경우에 작동합니다 :

내가 value1null이면 다음 과 같은 것을 value3 = value1 ?: value2하면 value2 가 반환되고 그렇지 않으면 value1 이 반환됩니다.

이 답변을 통해보다 명확한 이해를 얻을 수 있습니다 .


3

ifKotlin에서 표현식을 사용할 수 있습니다 . Kotlin 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
}

2

표준 표기법을 사용하지 않을 경우 다음과 같은 접두사 를 사용하여 표준 표기법을 작성 / 시뮬레이션 할 수도 있습니다 .

목표와 결과를 담을 클래스를 만듭니다.

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"

실제 삼항 연산자와 완전히 동일하게하기 위해 목표 값은 T
Old of Aran

1

사용하는 또 다른 짧은 접근법

val value : String = "Kotlin"

value ?: ""

여기에서 kotlin 자체는 null 값을 확인하고 null이면 빈 문자열 값을 전달합니다.


1

왜 이런 식을 사용하겠습니까?

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

실제로 다음과 같은 것을 사용할 수있을 때 ( a이 경우 부울입니다) :

when {
  a -> b
  else -> b
}

1
첫 번째는 코 틀린에 익숙하지 않은 사람이라도 의미를 명확하게 이해하고 쉽게 읽을 수 있기 때문에 두 번째 사람은 그렇지 않습니다.
mc01

1
글쎄, 당신은 요점을 알지만, Kotlin 개발자들이 왜 삼항 표현을 도입하지 않았는지 이해할 수 없습니다
ZZ 5

? and :형식 검사가 아니라 nullable / type 선언과 모순된다고 생각 합니다. 그것과 별개로 나는 어떤 이유도 보지 못한다. 인라인 if-else 조건 검사가 있다면 누군가가 분명히 몇 가지 생각을했을 것이라고 생각합니다. 다음 버전에서 기다려 보자.
bh4r4

1

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 함수를 사용하면 많은 일반적인 사용 사례를 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에는 삼항 연산자가 없으며 가장 닫힌 것은 다음 두 경우입니다.

  • 다른 표현 문으로

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

  • 엘비스 연산자

? :의 왼쪽에있는 표현식이 널이 아닌 경우 elvis 연산자는이를 리턴하고 그렇지 않으면 표현식을 오른쪽에 리턴합니다. 오른쪽 표현식은 왼쪽이 널인 경우에만 평가됩니다.

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

참조 문서


0

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

kotlin에서 ? 를 사용하는 경우 문이 null을 반환하고 ? : 0을 반환하는 것처럼 작동 합니다.


-1

Kotlin에서는 다음과 같이 삼항 연산을 사용할 수 있습니다. val x = if(a) "add b" else "add c"


1
이 질문은 이미 충분히 답변되었으며 최근에 업데이트되지 않았습니다. 이전 답변과 다른 답변을 게시 할 필요가 없습니다.
헤드 크래커

-2

다른 아이디어를 연구 한 후 다음과 같은 삼항 연산자를 도출했습니다.

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

예 ( 여기서 실행 ) :

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")
    }
}

이 버전은 유창하며 널 병합 연산자와 충돌하지 않습니다.


이것은 then대신 이름이 지정된 deviant의 답변과 동일 yes합니다.
Ry-

@Ry 예, 그리고 그들이 같은 사람인지 확실하지 않지만 옵션과 함께 infix 메소드를 사용하는 아이디어는 Kotlin 포럼에서 나옵니다. 내가 보지 못한 것은 물음표가 대부분의 언어에서와 같이 조건 대신 'the value'를 따르기 때문에 Null 병합 연산자의 인라인 사용이 혼란스러워서 생각해 낸 'no'방법입니다.
Bryan W. Wagner 19
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.