Bernardo Becker
Bernardo Becker

Reputation: 3

Kotlin: Is there any way to iterate this as a Sequence?

I am making a image filter, I already have this done, but I've read that for large collections it would be better to use a sequence for iteration, and since is a 8k image I suppose that I would gain some performance because of its lazy initialization with a Sequence<IntArray> instead of Array<IntArray>, or even Sequence<Sequence<Int>>. I don't know if this is possible yet, I'm quite confused and trying to learn this new paradigm for me, and I'm having difficult to find more easier material to understand the usage syntax of this concept.

This is what a tried, but is a mess, I don't have much idea of how to proceed this, or even if I should use the "newImage" as Sequence also.

val myPredicate = { array : IntArray -> !array.first() /*???*/ && !array.last() }
image.asSequence().forEach { array ->
    array.filter(myPredicate ) // ???
}

This is the functional code to be transformed:

fun chunker(image : Array<IntArray>) : Array<IntArray> {
    val arrayRowSize = image.size
    val arrayColSize = image[0].size
    val newImage : Array<IntArray> by lazy {
        Array(arrayRowSize) { IntArray(arrayColSize) }
    }

    var kernel = IntArray(9)
    // to translate to a Sequence those two for loops
    for (row in 1 .. arrayRowSize - 2) {
        for (col in 1 .. arrayColSize - 2) {
            kernel = changer(row, col, kernel, image)
            newImage[row][col] = kernel[4]
        }
    }
    return newImage
}

Upvotes: 0

Views: 1340

Answers (1)

Joffrey
Joffrey

Reputation: 37859

I've read that for large collections it would be better to use a sequence for iteration

What you have probably read is that, given a functional pipeline like myCollection.filter(...).map(...).first(...), performance can be improved by using a Sequence for mainly 2 reasons:

  1. the sequence won't process all elements if it doesn't have to (the first() and the end could make it terminate before seeing all elements)
  2. the sequence won't create intermediate collections for each pipeline step (like filter or map), unlike regular collections

In your case, you don't even have a pipeline of functional operations, and you don't create intermediate collections since you create and populate your result directly. Moreover, you can't terminate early because you want to process all pixels anyway, so Sequence might be appropriate but would not be necessarily a performance improvement here.

If you're compiling this Kotlin code targeting the JVM, then there is at least one thing you can do to improve performance:

Instead of using a 2D-array, use a 1D-array with a special indexing. More specifically, instead of newImage[row][col], you would write newImage[row * width + col]. This will avoid double memory references and benefit from cache locality, because you're iterating row by row.

Upvotes: 1

Related Questions