Simon
Simon

Reputation: 1737

Compare value against two values with 'or' operator

I have a simple if () condition which needs to check if value is either 1 or 2 (for example). Let's say the value we are comparing against is not 'simple':

if(it.first().property.value == 1 || it.first().property.value == 2) {
    // Do stuff
}

Is there a better way to perform this check (without typing the entire expression to get the actual value twice)? The only thing that comes to mind is

if(listOf(1, 2).contains(it.first().property.value)) {
    // Do stuff
} 

But I'm afraid it's more memory consuming since it has additional list introduced.

Upvotes: 1

Views: 411

Answers (3)

gidds
gidds

Reputation: 18557

Your last suggestion is a good one in general, though it's usually better to use a predefined list (and the in operator):

// At the top level, or in a (companion) object:
val acceptableValues = listOf(1, 2)

// Then in the relevant part of the code:
if (it.first().property.value in acceptableValues)
    // Do stuff

That only allocates the list once, and performance is about as good as any other option.  It's also very readable, and general.

(If the list doesn't naturally fit into a named property, you'd have to judge how often it might be needed, in order to trade a minor performance benefit against the conciseness of putting it directly in the condition.)

In fact, because you're looking for consecutive integers, there's a more concise option for this particular test:

if (it.first().property.value in 1..2)
    // Do stuff

That would work whenever the acceptable values form an (uninterrupted) range.

Alternatively, if you're always checking against exactly two values, you could write a simple extension function:

fun <T> T.isEither(a: T, b: T) = this == a || this == b

(You could write a more general one using a vararg param, but that would create an array each time — very similar to the in listOf() case we started with.)

Upvotes: 4

Jakub Zalas
Jakub Zalas

Reputation: 36191

You could define an extension function on the type of it to make it more readable:

if(it.isOneOrTwo()) {
    // Do stuff
}

Not sure what's the type of your it, replace TYPEOFIT accordingly:

private inline fun TYPEOFIT.isOneOrTwo() = first().property.value == 1 || first().property.value == 2

To additionally improve the condition you could leverage when:

private inline fun TYPEOFIT.isOneOrTwo() = when(first().property.value) {
    1,2 -> true
    else -> false
}

Upvotes: 3

deHaar
deHaar

Reputation: 18568

You can decide it using a when expression like in this example:

fun main() {
    val number = 22

    when (number) {
        1, 2 -> println("${number} is 1 or 2")
        in 10..20 -> println("${number} is between 10 and 20 (inclusively)")
        else -> println("${number} is either negative, equals 0, 3, 4, 5, 6, 7, 8, 9, 21 or any number above")
    }
}

The output here is

22 is either negative, equals 0, 3, 4, 5, 6, 7, 8, 9, 21 or any number above

Upvotes: 4

Related Questions