1

I am having trouble converting an if expression into a when expression in kotlin. My If code is as followed:

fun main() {
    var cardPoints = 7_000


    val cardLevel: String = if (cardPoints >= 0 && cardPoints < 1000) {
        "pearl"
    } else if (cardPoints >= 1000 && cardPoints < 5_000) {
        "silver"
    } else if (cardPoints >= 5_000 && cardPoints < 10_000) {
        "gold"
    } else {
        "platinum"
    }

    val plural = if(cardPoints > 1 || cardPoints == 0) "s" else ""
    println("You have $cardPoints point$plural and are at the $cardLevel level.")
}

However, I must now convert it into a "When" expression (preferably in ranges), this is what I have so far:

fun main() {
    var cardPoints = 7_000

    val cardLevel: String = when {
        cardPoints >= 0 && cardPoints < 1000 -> "pearl"

        cardPoints >= 1000 && cardPoints < 5_000 -> "silver"

        cardPoints >= 5_000 && cardPoints < 10_000 -> "gold"
        else -> "platinum"

    }
    val plural = if(cardPoints > 1 || cardPoints == 0) "s" else ""
    println("You have $cardPoints point$plural and are at the $cardLevel level.")
}

I am unsure on what else needs to be tweaked or if I am missing something entirely. I would be thankful for any help and suggestions. Thanks.

1
  • Not as much an answer but a tip: Instead of manually converting, if you are using Android Studio or IntelliJ there is an automatic way. You can move your cursor on if, press Alt+Enter and select "Replace if with when". This way has the benefit that it prevents errors that could potentially happen when manually converting code. Commented May 25, 2020 at 12:54

3 Answers 3

6

You can use range with an in operator to solve the problem.

var cardPoints = 7000
val cardLevel: String = when {
    cardPoints in 0..999 -> "pearl"

    cardPoints in 1000..4999 -> "silver"

    cardPoints in 5000..9999 -> "gold"

    else -> "platinum"

}
Sign up to request clarification or add additional context in comments.

5 Comments

but ranges should end with 999, 4999 and 9999, right?
@tpschmidt You're correct. I fixed the answer. Thanks.
hmm I tried this method of using in but unfortunately, I receive an error: Unresolved reference: cardPoints?
I took the relevant snippet from the original question. Define the variable before the when expression.
It finally worked! To both tpschmidt and @AndrejH Thank you for the help :) I was receiving the error i mentioned above because the end of the ranges were off.
2

you can use also

fun main () {
    var cardPoints = 7_000

    val cardLevel: String = when(cardPoints) {
        in 0..1000 -> "pearl"
        in 1000..5000 -> "silver"
        in 5000..10000 -> "gold"
        else -> "platinum"
    }

    val plural = if(cardPoints > 1 || cardPoints == 0) "s" else ""
    println("You have $cardPoints point$plural and are at the $cardLevel level.")
}

Comments

1

A simpler (and more efficient) approach: just omit the range and take advantage of the order of when-evaluation:

when {
  cardPoints < 0 -> error("this probably shouldn't be platinum, right?")
  cardPoints < 1000 -> "pearl"
  cardPoints < 5000 -> "silver"
  cardPoints < 10000 -> "gold"
  else -> "platinum"
}

This also holds true of course for your if itself:

if (points < 0) error("not platinum, right?")
else if (points < 1000) "pearl"
else if (points < 5000) "silver"
else if (points < 10000) "gold"
else "platinum"

In both cases you do not have to repeat, what was already evaluated one step earlier, e.g. if it isn't lower than 0, the next condition doesn't need to repeat >= 0, because we already know it isn't < 0 and it can only be >= 0 at the next point. Same if it is not lower than 1000, the next condition doesn't need to repeat, that it is >= 1000. If you will, you can simplify each if (x) else if (!x && y) to if (x) else if (y)...

If you use ranges, just keep in mind that it will be much slower (on my machine with a factor of ~3-4), which of course you can ignore, if performance is not an issue.

If my assumption that < 0 is not platinum is wrong, then I would probably just return "platinum" there as well instead of using ranges.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.