Kotlin Üçlü Koşullu Operatör


Yanıtlar:


619

Kotlin'de ififadeler ifadelerdir. Yani aşağıdaki kod eşdeğerdir:

if (a) b else c

Burada ifade ile ifade arasındaki ayrım önemlidir. Java / C # / JavaScript'te, ifbir değere çözümlenmediği anlamına gelen bir ifade oluşturur. Daha somut olarak, bir değişkene atayamazsınız.

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

İfadenin olduğu bir dilden geliyorsanız if, bu doğal görünmeyebilir, ancak bu duygu yakında azalmalıdır.


57
Ayrıca kullanabilirsiniz when.
bashor

5
sadece eklemek için, eğer boolean bir ifade ise, bile gidebilirsinizx = a==b
gnomeria

2
@MikeRylander Bunu açık yapmak için cevabı uzattım. Bunu işaret ettiğiniz için teşekkürler.
Drew Noakes

1
@AdeelAnsari Hayır, düzeltici değil. Bu daha da kötü. Bunu karşılaştırın. b + if (a) c else dvs b + (c if (a) else d)ikincisi bir ek parantez gerektiriyor. Çünkü ckoşul ve çevrelediği değildir else.
Naetmul

1
İşte bu konuyla ilgili küçük bir tartışma. tartışmak.kotlinlang.org/t/ternary
F. Norbert

70

Kendi tanımlayabiliriz Booleandonduğu uzatma işlevi olan üçlü operatör benzer bir yapı sağlamaktır:nullBooleanfalse

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

Bu, bir a ? b : cifadenin şu şekilde tercüme edilmesini sağlar a then b ?: c:

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

Güncelleme: Ama Java benzeri bir koşullu anahtar yapmak için böyle bir şeye ihtiyacınız olacak

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

println(condition then { "yes" } ?: "no") lambda'ya dikkat et. biz yapana kadar içeriği hesaplama emin ertelenmelidir conditionolduğunutrue

Bu beceriksiz görünüyor, bu yüzden Java üçlü operatörünü Kotlin'e taşımak için yüksek talep var


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

3
<T: Any> kullanın, aksi takdirde yanlış çalışır:true then { null } ?: "not-null"
Eugene Petrenko


64

TL; DR

if (a) b else c

üçlü operatör ifadesi yerine kullanabileceğiniz şeydir a ? b : c.


Kotlin'de, ifadeler dahil if, whenhatta ifadetry olarak birçok kontrol ifadesi kullanılabilir . Bu, bunların bir fonksiyondan döndürülen bir değişkene atanabilen bir sonuca sahip olabileceği anlamına gelir.

Sözdizimsel olarak üçlü operatöre gerek yoktur

Kotlin'in ifadelerinin bir sonucu olarak, dilin üçlü operatöre gerçekten ihtiyacı yoktur .

if (a) b else c

üçlü operatör ifadesi yerine kullanabileceğiniz şey budur a ? b : c.

Fikir, herkesin ne yaptığını bildiği için eski ifadenin daha okunabilir ifelseolduğu, ancak ? :söz dizimine aşina değilseniz, oldukça net olmadığı fikridir .

Yine de, daha uygun üçlü operatörü kaçırdığımı itiraf etmeliyim .


Diğer Alternatifler

ne zaman

whenKoşullar kontrol edildiğinde Kotlin'de kullanılan yapıları da görebilirsiniz . Ayrıca if-else basamaklarını alternatif bir şekilde ifade etmenin bir yoludur. Aşağıdakiler OT örneğine karşılık gelir.

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

Uzantıları

Diğer cevaplardaki birçok iyi örnek ( Kotlin Üçlü Koşullu Operatör ) gösterdiği gibi, uzantılar da kullanım durumunuzu çözmenize yardımcı olabilir.


36

Kendim için aşağıdaki uzantı işlevlerini kullanıyorum:

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

Birincisi, nesnenin null değerine eşit olması durumunda sağlanan varsayılan değeri döndürür. İkincisi, aynı durumda lambda'da sağlanan ifadeyi değerlendirecektir.

Kullanımı:

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

Şahsen benim için ifinşaat inlining daha okunabilir kod


34
Bu soru ile ilgili değil, ama neden kullanmıyorsunuz ?: , Elvis operatörü ? İlk işlev ile değiştirilir e.getMessage() ?: "unknown". İkinci olarak ifade edilebilirobj?.lastMessage?.timestamp ?: { Date() }()
kısayol tuşu

1
@hotkey bunun özel bir amacı yok. Benim açımdan, parantez içindeki inşaatı
sarmamanız

14
@ruX elvis operatörü özellikle bunun içindir ve kullanımınız olağandışıdır.
Jayson Minard

6
?: İyi olsa da, Perl yolunda çok ileri gitmeyelim.
Richard Haven


28

Orada hiçbir Üçlü operatör KOTLIN olduğu gibi if elseblok döner değeri

böylece şunları yapabilirsiniz: val max = if (a > b) a else b java yerinemax = (a > b) ? b : c

whenİnşaatı da kullanabiliriz , ayrıca değer döndürür:

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

Kotlin belgeleri için link: Kontrol Akışı: eğer, ne zaman, için, süre


27

Kotlin'de ifbir ifadedir, yani bir değer döndürür. Bu nedenle üçlü bir operatör yoktur (condition ? then : else), çünkü sıradan eğer bu rolde iyi çalışır. buradan manuel kaynak

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

Diğer cevaplarda belirtilmeyen bazı köşe vakaları.

Görünümünü yana takeIf içinde KOTLIN 1.1 üçlü operatör a ? b : cde bu gibi ifade edilebilir:

b.takeIf { a } ?: c

Bu c'nin olması durumunda daha da kısalır null:

b.takeIf { a }

Ayrıca Java dünyasında tipik olan null kontrollerin value != null ? value : defaultValueideomatik Kotlin dilinde adil olarak tercüme edilmesi gibi olduğunu da unutmayın value ?: defaultValue.

Benzer bir a != null ? b : cdile çevrilebilir a?.let { b } ?: c.


6
Ne kadar b.takeIf { a } ?: ckısa ve okunabilir if (a) b else c? Terneray operatörü Kotlin'de kesinlikle eksik bir özelliktir, çünkü değişken isimleri ve durum uzun olabilir ve kötü olan çizgiyi
bölmenizi sağlayabilir

1
Ayrıca takeIfher zaman gerçek durumu değerlendirdiğine dikkat edilmelidir (burada a). Bu ifade ayanlış olduğu takdirde işe yaramaz bir şekilde hesaplanmakla kalmaz, aynı zamanda akıllı yayınlardan da yararlanamazsınız if (a is Int) { a + 3 }.
TheOperator

@Operator, yanlış. { a }tembel olarak değerlendirilen bir lambdadır.
Vadzim

1
Yanlış yazdım, "her zaman gerçek vakayı değerlendirir (burada b)" olmalı . Ama { a }, tembel ise, gereken ifadenin sonucunu belirlemek için değerlendirilecek.
TheOperator

24

Dokümanlara bir göz atın :

Kotlin'de, eğer bir ifade ise, yani bir değer döndürür. Bu nedenle üçlü bir operatör (koşul? Sonra: başka) yoktur, çünkü bu rolde iyi çalışırsa sıradan.


13

Java

int temp = a ? b : c;

Kotlin : ile eşdeğerdir

var temp = if (a) b else c

12

GÖREV :

Aşağıdaki örneği ele alalım:

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

Kotlin'de şu eşdeğere ihtiyacımız var:

return (! answer.isSuccessful ()) ? "yanlış" : answer.body (). string ()


ÇÖZÜMLER :

1.a . if-expressionKotlin'de kullanabilirsiniz :

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

1.b . Bunu çevirirseniz çok daha iyi olabilir if-expression(hadi olmadan yapalım not):

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

2 . Kotlin'in Elvis operatörü ?:bir işi daha da iyi yapabilir:

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

3 . Veya Extension functionilgili Answersınıf için bir kullanın :

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

4 . Kullanarak Extension functionbir kodu azaltabilirsiniz Elvis operator:

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

5 . Veya yalnızca whenoperatörü kullanın :

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

Bu yardımcı olur umarım.


11

C benzeri dillerin anahtar operatörünün yerini aldığında. En basit haliyle şöyle görünür

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

3
Doğru, ancak gösterdiğiniz örnek whenbir ifade değil, bir ifade olarak vardır. Üçlü koşullu ifadelerle daha alakalı bir karşılaştırma, her dalın bir değer döndürmesini sağlamaktır, böylece ifade bir değer olarak değerlendirilirse (üçlü koşullarda olduğu gibi).
Drew Noakes

9

Kotlin'de üçlü operatör yoktur. İlk bakışta sorunlu görünüyor. Ama bunu başka bir ifadeyle inline ile yapabileceğimizi düşünün çünkü bu burada ifade. Sadece yapmalıyız -

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

Burada ihtiyacımız olduğu kadar çok blok varsa başka yapabiliriz. Sevmek-

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

Yani bu çizgi üçlü operatörden çok basit ve okunabilir. Java'da birden fazla üçlü operatör kullandığımızda korkunç görünüyor. Ama burada açık bir sözdizimimiz var. hatta birden çok satırda da yazabiliriz.


9

Kullanabilirsiniz var a= if (a) b else cÜçlü operatör yerine .

Kotlin'in bir başka iyi konsepti Elvis operatörüdür. Her seferinde null değerini kontrol etmenize gerek yoktur.

val l = b?.length ?: -1

B boş değilse bu uzunluk döndürür, aksi takdirde sağ taraf deyimini yürütür.


7

Drew Noakes'ın belirttiği gibi, kotlin if ifadesini ifade olarak kullanır, bu nedenle artık Üçlü Koşullu Operatör gerekli değildir,

ancak uzantı işlevi ve aşırı yükleme ile, bunu kendiniz uygulayabilirsiniz, işte bir örnek

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
}

o zaman böyle kullan

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

Belki <T> daha iyi? infix eğlencesini kaldırın veya (falsy: T?) = Eğer (bayrak) gerçekten başka bir falsy
solo

1
Ama ekleyin <T> işe yarayabilir: (grade> 80) sonra null veya "B"
solo

Bu gerçekten harika, ben kullanacağım: P Ama yanılmıyorsam, her çağrıldığında bir nesne tahsisine neden olacağını unutmayın. Büyük bir anlaşma değil, ama sıfır maliyet soyutlama olmadığını bilmeye değer.
Adam

6

Bir başka ilginç yaklaşım kullanmak olacaktır when:

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

Bazı daha karmaşık senaryolarda oldukça kullanışlı olabilir. Ve dürüst olmak gerekirse, benim için daha okunabilirif ... else ...


6

Kotlin'de birçok şekilde yapabilirsiniz

  1. Eğer

    if(a) b else c
  2. Ne zaman kullanılır?

    when (a) { 
        true -> print("value b") 
        false -> print("value c") 
        else -> {  
            print("default return in any other case") 
        } 
    }
  3. Boş Güvenlik

    val a = b ?: c

5

Kotlin'de üçlü bir operasyon yok, ancak bunun üzerinde çalışmanın eğlenceli yolları var. Diğerlerinin de belirttiği gibi, Kotlin'e doğrudan bir çeviri şöyle görünecektir:

val x = if (condition) result1 else result2

Ancak, kişisel olarak, bunun biraz karmaşık ve okunması zor olabileceğini düşünüyorum. Kütüphanede yerleşik olan başka seçenekler de var. TakeIf {} 'yi bir elvis operatörü ile kullanabilirsiniz:

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

Burada olan şey takeIf {} komutunun sonuç1 veya null değerini döndürmesi ve elvis operatörünün null seçeneğini işlemesi. Bazı ek seçenekler var, takeUnless {}, örneğin:

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

Dil açık, ne yaptığını biliyorsun.

Yaygın olarak kullanılan bir durumsa, satır içi uzantı yöntemi kullanmak gibi eğlenceli bir şey de yapabilirsiniz. Örneğin bir oyun skorunu Int olarak izlemek istediğimizi ve belirli bir koşul karşılanmadığında her zaman 0 döndürmek istediğimizi varsayalım:

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

Tamam, bu çirkin gözüküyor. Ancak kullanıldığında nasıl göründüğünü düşünün:

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

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

Gördüğünüz gibi, Kotlin kodunuzu nasıl ifade edeceğiniz konusunda çok fazla esneklik sunuyor. Örneklerimin sayısız varyasyonu ve muhtemelen henüz keşfetmediğim yollar var. Umarım bu yardımcı olur!


takeIfen sevdiğim seçenek gerçekten çok şık.
Javier Mendonça

4

Ternary operatörü ve Elvis operatörünün birçok popüler dilde aksine Kotlin'de ayrı anlamları olduğunu unutmayın . Doing expression? value1: value2tarafından size kötü sözler verecekti Kotlin olarak orada başka bir dile benzemeyen, derleyici KOTLIN hiçbir Üçlü operatör belirtildiği gibi resmi dokümanlar . Bunun nedeni, if, when ve try-catch deyimlerinin kendilerinin değer döndürmesidir.

Böylece, expression? value1: value2yerine

val max = eğer (a> b) yazdır ("Bir" seç ") başka yazdır (" b seç ")

Elvis operatör olduğunu Kotlin vardır, sadece null değişkenler eski halinde çalışır .:

Ben böyle bir şey yapmak value3 = value1 ?: value2o zaman deger1 olduğunu boş sonra deger2 iade edileceği aksi deger1 iade edilecektir.

Bu cevaplardan daha açık bir anlayış elde edilebilir .


3

Bunun için ififadeyi Kotlin'de kullanabilirsiniz. Kotlin'de ifsonuç değeri olan bir ifadedir. Kotlin’de

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

ve Java'da aynı şeyi yapabiliriz ancak daha büyük kodla

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

2

Standart gösterimi ne kullanamazsanız, böyle bir şeyle infix kullanarak da oluşturabilir / simüle edebilirsiniz :

hedefinizi ve sonucunuzu korumak için bir sınıf oluşturun:

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

üçlü bir işlemi simüle etmek için bazı infix işlevleri oluşturma

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
}

O zaman bu şekilde kullanabilirsiniz:

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"

Gerçek bir üçlü operatöre tamamen eşdeğer olması için, hedef değerler ayrıca
Old Man'ı

1

Kullanıma başka bir kısa yaklaşım

val value : String = "Kotlin"

value ?: ""

Burada kotlin null değerini kontrol eder ve null ise boş dize değerini geçer.


1

Neden böyle bir şey kullanılsın:

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

aslında böyle bir şey kullanabildiğinizde ( abu durumda boole'dir):

when {
  a -> b
  else -> b
}

1
Çünkü birincisi anlamsal olarak açıktır ve Kotlin'e aşina olmasalar bile, okuyan bir başkası tarafından kolayca anlaşılabilir, ikincisi ise değildir.
mc01

1
Peki, bunun anlamı var, ancak Kotlin geliştiricilerinin neden üçlü ifadeyi tanıtmadıklarını anlayamıyorum
ZZ 5

Bence ? and :bir tür kontrol yerine null / tür bildirimi ile çelişiyor. Bunun dışında hiçbir neden göremiyorum. Satır içi if-koşul kontrolü varsa, birisi kesinlikle biraz düşünürdü düşünüyorum. Bekleyelim ve gelecek sürümlerde görelim.
bh4r4th

1

Uygula () ile çalışırken, üçlü işlemlerle uğraşırken çok daha kullanışlı görünmesine izin verin, çünkü daha zarif ve size yer verin

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

Aşağıdaki infix işlevleriyle Python'da olduğu gibi birçok yaygın kullanım örneğini kapsayabilirim:

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'de üçlü bir operatör yok, en kapalı olan aşağıdaki iki durum,

  • İfade ifadesi olarak başka ise

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

  • Elvis operatörü

?: Öğesinin solundaki ifade null değilse, elvis operatörü bunu döndürür, aksi takdirde ifadeyi sağa döndürür. Sağ taraftaki ifadenin yalnızca sol taraf boş olduğunda değerlendirildiğini unutmayın.

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

Referans dokümanlar


0

örnek: var energy: Int = veri? .get (pozisyon) ?. enerji? .toInt ()?: 0

KOTLIN size kullanıyorsanız :? O deyimi sonra return null eğer gibi çalışacak 0: Durum 0 alacak veya bu tarafını yazmak ne varsa.


-1

Kotlin'de üçlü işlemi şu şekilde kullanabilirsiniz: val x = if(a) "add b" else "add c"


1
Bu soru zaten yeterince cevaplandı ve yakın zamanda güncellenmedi. Şimdi öncekilerden farklı olmayan başka bir cevap göndermeye gerek yok.
Headcracker

-2

Diğer fikirleri araştırdıktan sonra, aşağıdaki üçlü operatörü türettim:

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

Örnek ( burada çalıştırın ):

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

Bu sürüm akıcıdır ve boş birleştirme operatörü ile çakışmaz.


Bu, adının thenyerine deviant'ın cevabı ile aynıdır yes.
Ry-

@ Evet, ve aynı kişi olup olmadığından emin değilim ama opsiyonellerle infix yöntemlerini kullanma fikri Kotlin forumundan geliyor. Görmediğim, ortaya çıkardığım 'hayır' yöntemidir çünkü null birleştirme operatörünün satır içi kullanımını kafa karıştırıcı buluyorum çünkü soru işareti çoğu dilde olduğu gibi yerine 'o zaman değer'in peşinde.
Bryan W. Wagner
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.