Open In App

Multiconditional Loop in Kotlin

Last Updated : 23 Jan, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

As we all know about loops, in Kotlin, loops are compiled down to optimized loops wherever possible. For example, if you iterate over a number range, the bytecode will be compiled down to a corresponding loop based on plain int values to avoid the overhead of object creation. Conditional loops are common to any programming language you pick. If you apply multiple conditions to a loop, it is called a multiconditional loop. A simple example of a multiconditional loop in Java is illustrated here:

Kotlin




import java.io.*;
  
class GFG {
    public static void main (String[] args) {
      int [] data = {5, 6, 7, 1, 3, 4, 5, 7, 12, 13};
      for (int i=0; i<10 && i < data[i];i++) {
        System.out.println (data[i]);
      }
   }
}


The preceding code on execution will print out 5, 6, and 7. Let’s see how we can use a multiconditional loop in Kotlin. We will be looking at a functional approach to the same thing in Kotlin

Example

The preceding multiconditional loop can be written in Kotlin like so:

Kotlin




(0..9) .asSequence ( ) .takeWhile {
  it<numbers [it]
}.forEach
    println( "$it - ${data[it]}")
}


It’s nice, clean, and definitely not an eyesore.

  • We used takeWhile, which returns a sequence containing the first elements satisfying the given predicate (in this case, i <data [i]).
  • Though takewhile returns the first elements that satisfy the given predicate, you might be tempted to think that it will first evaluate the complete range and then pass to forEach.
  • That would have been the case if we hadn’t used .asSequence (). We converted the range to a Sequence<T>, and because of this, it was lazily evaluated. In short, it won’t process the whole set of items with .takeWhile { … } and will only check them one by one when .forEach { . . . }is up to process the next item.

First, we will work with an eager evaluation over Iterable<T>. This is the eager version, which evaluates the first function before moving on to the next one:

Kotlin




(0..9).takeWhile {
  println{"inside takewhile"}
  it<numbers[it]
}.forEach
    println( "inside forEach")
}


Output:

Inside takeWhile
Inside takeWhile
Inside takeWhile
Inside takewhile
Inside forEach
Inside forEach
Inside forEach

As you can see, the range was first processed with takewhile (which returned 0, 1, 2) and was then sent for processing to forEach. Now, let’s see the lazy version:

Kotlin




(0..9).asSequence().takewhile {
  printin ("Inside takewhile")
  it <numbers[it]
}.forEach{
  printin ("Inside forEach")
}


Output:

Inside takewhile
Inside forEach
Inside takewhile
Inside forEach
Inside takewhile
Inside forEach
Inside takewhile

As you can see in the preceding example, takewhile is evaluated only when forEach is used to process an item. This is the nature of Sequence<T>, which performs lazily where possible.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads