Bubblebees
Bubblebees

Reputation: 63

Return first non-null value after transformation in Kotlin

I'd like to return the first non-null value after the transformation of a list of elements in Kotlin, so something like this:

suspend fun myFunction(): Any {
    val firstNonNullId = this.mapNotNull{ it.id }
        ?.first{ transform(id) != null }

    return transform(firstNonNullID)
}

What would be a better and more idiomatic way to write this function? I'd like to call upon transform(it) as few times as possible, and the transformation in question is also a suspend function.

Edit: The asSequence() solution gives an error when the transform() is a suspend function, as it must be called from a coroutine body. This happens even if the overall myFunction() is a suspend function. What should the solution be when the transformation is a suspend function?

Upvotes: 5

Views: 3845

Answers (2)

Ilya
Ilya

Reputation: 23115

Since Kotlin 1.5, you can use firstNotNullOf function or its ...OrNull variant:

// returns the first non-null result of transform
this.firstNotNullOf { transform(it.id) }  

firstNotNullOf throws an exception if no non-null result of the transformation is found, and firstNotNullOfOrNull returns null in this situation.

Both functions are inline, so it should be possible to call suspend functions in their lambda parameters when they are themselves invoked from a suspend function.

Upvotes: 8

Mikhail Burshteyn
Mikhail Burshteyn

Reputation: 5002

I would suggest to use Kotlin sequences:

this.asSequence()
    .mapNotNull { it.id }
    .mapNotNull { transform(it) }
    .first()

Since sequence evaluation is lazy, your transform function will only be called during the call to .first(), and it will not be called after the first non-null result is obtained.

Upvotes: 2

Related Questions