Reputation: 7117
I would like to write a function in Kotlin which takes a String array and sums up the length of all items in the array. I thought about something like this:
fun sumItems(values: Array<String?>): Int {
var sum: Int = 0
values.forEach { if(it != null) sum += it.length }
return sum
}
This works great but unfortunately I can not call this method for Array<String>
because I get a type mismatch error then. I also can not create a function sumItems(values: Array<String>): Int
because it has the same JVM signature. I could cast my argument to Array<String?>
but this is unsafe.
So is there any better way to do this in Kotlin?
Upvotes: 0
Views: 355
Reputation: 23232
Even though Yoni Gibbs answer is correct, I would rather take another route here, i.e. working with a non-nullable type, e.g.:
fun sumItems(values: Array<String>) = values.sumBy { it.length }
And as also m0skit0 mentioned in the comment: if you really have null
values in your list, filter them out before making the sum, e.g.:
val arrayWithNulls = arrayOf("hello", null, "world")
arrayWithNulls.filterNotNull()
.let(::sumItems)
Or better yet: just skip that method and do:
arrayWithNulls.filterNotNull()
.sumBy { it.length } // or .sumBy(String::length)
Why introducing a new function, if applying existing ones already suffices?
Try to eliminate the null values from your array early. Otherwise your code just gets more complex (adding lots of null-safe things) and that makes the code just less readable. That way you could also skip that filterNotNull
.
Upvotes: 2
Reputation: 7018
Try this:
fun sumItems(values: Array<out String?>) = values.sumBy { it?.length ?: 0 }
You might want to make it an extension method instead:
fun Array<out String?>.sumItems() = sumBy { it?.length ?: 0 }
This will work for both Array<String>
and Array<String?>
because of the out
modifier on the generic type. What this states is that the values
parameter (or the receiver of the extension method) must be an array that produces nullable strings. Obviously Array<String?>
produces nullable strings so that's valid to pass in. But Array<String>
also produces nullable strings, because strings can always be cast to nullable strings. This is explained in more detail here.
Upvotes: 2