I need to check if none of the values in two IntArray objects differ by more than 1.
This is the working code, which takes too long:
var pixelOutsideOfTolerance = false
val PIXEL_VALUE_TOLERANCE = 1
for (i in 0 until pixels1.lastIndex) {
if (pixels1[i] - pixels2[i] > PIXEL_VALUE_TOLERANCE && pixels1[i] - pixels2[i] < - PIXEL_VALUE_TOLERANCE) {
pixelOutsideOfTolerance = true
}
}
// Do something with pixelOutsideOfTolerance
What would be a more performant and eloquently way to do this?
CodePudding user response:
Before fixing performance, you must ensure correctness:
- you have an off-by-one error because
lastIndex
is the actual last index, not the size. Usefor (i in pixels1.indices)
instead of explicit ranges to avoid this kind of mistakes - your condition can never be true, because you're using
&&
instead of||
. Useabs(pixels1[i] - pixels2[i]) > PIXEL_VALUE_TOLERANCE
instead of the more complicated condition checking both positive and negative, it will be simpler to read and less likely to get wrong (you'll needimport kotlin.math.abs
)
Now you're doing the whole loop even when you already know some pixel differences are outside the tolerance. Extract a function for this loop, and return early when the "outside tolerance" condition is met.
Applying the above, you should now have:
import kotlin.math.abs
private const val PIXEL_VALUE_TOLERANCE = 1
private fun areSimilar(pixels1: IntArray, pixels2: IntArray): Boolean {
for (i in pixels1.indices) {
if (abs(pixels1[i] - pixels2[i]) > PIXEL_VALUE_TOLERANCE) {
return false
}
}
return true
}
// then just use
val pixelsOutsideOfTolerance = !areSimilar(pixels1, pixels2)
If performance was not a requirement, you could also use a more functional approach here. For instance:
val pixelsOutsideOfTolerance = pixels1.indices.any {
abs(pixels1[it] - pixels2[it]) > PIXEL_VALUE_TOLERANCE
}
Or:
val pixelsOutsideOfTolerance = pixels1.asSequence().zip(pixels2.asSequence())
.any { abs(it.first - it.second) > PIXEL_VALUE_TOLERANCE }
But if it's really a hot path that you are trying to speed up, that will be counter-productive because of boxing.