Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change for loop index in Kotlin

How can I modify the loop variable in Kotlin?

For my particular case, I have a for-loop in which, for certain conditions, I want to skip the next iteration:

for(i in 0..n) {
  // ...
  if(someCond) {
    i++ // Skip the next iteration
  }
}

However, when I try this, I'm told that "val cannot be reassigned".

like image 396
Kricket Avatar asked Jan 26 '18 09:01

Kricket


People also ask

Can you index in a for loop?

Using enumerate() method to access index enumerate() is mostly used in for loops where it is used to get the index along with the corresponding element over the given range.

Is there a for loop in Kotlin?

In Kotlin, the for loop is used to loop through arrays, ranges, and other things that contains a countable number of values. You will learn more about ranges in the next chapter - which will create a range of values.

How do you iterate through a list in Kotlin?

We can use the listIterator() method for iterating through lists in both forward and backward directions.


2 Answers

You can't mutate the current element, you would need to use a while loop instead:

var i = 0
while (i <= n) {
    // do something        
    
    if (someCond) {
        i++ // Skip the next iteration
    }

    i++
}

What are you trying to do? There is a chance there is a more idiomatic way to do this.

If you could restructure this logic to skip the current iteration, why not use continue:

for (i in 0..n) {
    if (someCond) {
        continue
    }
    // ...
}

Side note: .. ranges are inclusive, so to loop through e.g. a list of size n you usually need 0..(n - 1) which is more simply done with until: 0 until n.


In your specific case, you can use windowed (Kotlin 1.2):

list.asSequence().filter { someCond }.windowed(2, 1, false).forEach { 
    val (first, second) = it
    // ...
}

asSequence will convert the list into a Sequence, removing the overhead of filter and windowed creating a new List (as they will now both return Sequences).

If you want the next pair to not include the last element of the previous pair, use windowed(2, 2, false) instead.

like image 94
Salem Avatar answered Oct 11 '22 12:10

Salem


It looks like what you're really trying to do is iterate a sliding window of size 2 over a list. If you're using kotlin 1.2 or later, you might use the List.windowed() library function.

For example, to consider each pair of adjacent elements, but discarding the ones where the second of the pair is negative, you would do:

val list = listOf(1, 2, 3, -4, -5, 6)
list.windowed(2,1).filter { it[1] > 0 }.apply(::println)

Which would print out

[[1, 2], [2, 3], [-5, 6]]

having skipped the pairs [3, -4] and [-4, -5]

like image 27
Hank D Avatar answered Oct 11 '22 10:10

Hank D