Pass all in a list starting from index

Just for a case: could be this structure simplified without losing performance O(N) (including memory)?

    fun passAllFrom(index: Int, action: (bar: Bar) -> Unit) {
        (index until list.size).forEach { action(list[it]) }
        (0 until index).forEach { action(list[it]) }
    }

Your question is enigmatic. What do you want to simplify? Flattening matrix into a list? Iterating over a list starting from a given index? What is N? You use 2D structure, so the time complexity is more like M*N already, not just N, but that really depends on specifics of this matrix.

2 Likes

Yep, sorry, excluded unnecessary code. The topic is the case. Need to pass all items in a list starting from index.

You could do this:
(0 until list.size).forEach{ action(list[(it + index) % list.size]) }

1 Like

Thanks. I thought to manipulate indexes, looks like it’s a solution.

Please note such operation is often called “rotating”, in this case rotating left. “Rotating” is usually used when working with integers and their bits, but I think it would be clear for most developers in the case of lists/arrays as well.

You can create a simple extension function to make your code cleaner:

// copying implementation
fun <T> List<T>.rotatedLeft(count: Int): List<T> = List(size) { this[(it + count) % size] }

// lazy implementation
fun <T> List<T>.asRotatedLeft(count: Int): List<T> = object : AbstractList<T>() {
    override val size = this@asRotatedLeft.size
    override fun get(index: Int) = this@asRotatedLeft[(index + count) % size]
}

Please be aware both above implementations are optimized for random access lists, they won’t work well with e.g. linked lists.

1 Like

Thanks. I see, if it’s a common operation, maybe it’s nice to implement it in Kotlin by default?

Not a common enough operation to warrant putting in the standard library.

To follow onto broot’s implementation I would have it return a sequence, not a list because there is a cost to making a list if you don’t need it (which your example did not need). You can always add .toList() after the call to convert to a list.

So here is an alternate implementation (untested):

fun <T> List<T>.rotatedLeft(count: Int): Sequence<T> =
    asSequence()
        .run { drop(count % size) + take(count % size) }
3 Likes

Looks common enough for a Python library.