## DEV Community

Christian Vasquez

Posted on

# Look ma', without loops!

_Cover image by [@jordaneil](https://unsplash.com/@jordaneil) from [Unsplash](https://unsplash.com/)_

I would highly recommend you, Mr/Mrs Reader, to be familiar with the following concepts in order to fully understand this article:

1. Functions
2. Classes
3. Objects
4. Properties/Fields/Member Variables
5. Loops(`for`, `while`, `for-each`)

During one of my first few programming classes in college, I was introduced to an exercise/challenge by our teacher that said:

"Find the the amount of people that are above and below the average out of all the students's scores in a subject that are stored inside of an array."

He gave us clues as to how to start since he recently showed us about variables, functions and loops.

And the first thing that came to my mind was:

"We can use a few for-each loops here and there and then... WAIT! No. Let's do this without for/while loops!"

And as any Modern Developer Wannabe who thinks the only thing that exists is the JVM, I tried to do it in Kotlin ðŸ¤“

(What? did you think I was gonna use Java? Excuse you!)

## The Plan

Like any millennial, I always go to the grocery store armed with a shopping list so I don't forget anything. So, let's plan out what we'll need to do for this exercise:

1. We will need a way to represent a `Student` in our code. Let's keep it simple and declare a `class` with two properties: `name` and `score`.
2. Later on, we will need to store each one of them inside of an array that we will operate on.
3. And we will need to calculate the `average` of all of them.
4. Then we can use this value to compare it against each and every `Student` in our array to count how many of them are above and below the `average`.

## The Execution

### Making the `Student` class

Why? Because we can! (It can actually make our code easier to read once you finally understand what a class is)

Now, remember: we need to have two properties: `name` and `score`. Which will be their data types?

Yeah, you are totally right! `name` will be a `String` and `score` will be `Int`.

Here's how that code would look like:

``````class Student(val name: String, val score: Int)
``````

Beautiful!

For those that are not familiar with the `val` keyword, it means that this property is read only, so it's value can only be read, not modified by anyone after it has been set.

### Making the array of students

Over on this step I'll be using one of Kotlin's "voodoo magic" to make our `Array<Student` happen, here's how it looks:

``````fun main(args: Array<String>) {
val students = arrayOf(
Student("Chris", 80),
Student("Mark", 67),
Student("Joseph", 98),
Student("Carl", 74),
Student("Katherine", 86)
)
}
``````

Ulala!

Here we made use of the `arrayOf()` function provided by the Standard Library which serves as a piece of syntactic sugar at which we pass in a bunch of `Student` objects that we will work with (Feel free to alter any of the `names` or `scores` if you like).

Notice that we don't have to specify a data type for our `Array<T>` because the compiler can infer it from each argument we pass in to this function.

### Finding the average

This is where the fun starts, since we don't want to use any `for`/`while`/`for-each` loop, we will rely some Higher-Order functions.

#### Introducing... `sumBy {...}`

This function takes in a expression (or Lambda Expression to be more specific) which will then be used to calculate a single value, based on that expression.

Yeah, yeah, yeah... I know. It's sounds really boring.

Let's take a look at it:

``````students.sumBy { it.score }
``````

What we are doing here is iterating over each individual `Student` (which we are referring as "it") inside our `students` array, then taking only their `score`s and then adding them together to get one single value.

So, we can use this in order to calculate the `average`.

In order to do so, we will need to not only add all the scores together, but also divide it by the amount of `students`.

We can get that value by simply calling `students.size`, which in this case would give us `5`.

If we put it all together, we would have something like:

``````
fun calculateAverageScore(students: Array<Student>) = students.sumBy { it.score } / students.size

``````

Here I made use of a function in order to add more meaning to the operation we will be doing.

In case you might be wondering, we are allowed to remove the curly braces (`{`, `}`) and the `return` keyword if our function is only one line long.

Now we can use our trusty `calculateAverageScore()` function to help us out like this:

``````fun main(args: Array<String>) {
val students = arrayOf(
Student("Chris", 80),
Student("Mark", 67),
Student("Joseph", 98),
Student("Carl", 74),
Student("Katherine", 86)
)

val average = calculateAverageScore(students)
}

private fun calculateAverageScore(students: Array<Student>) = students.sumBy { it.score } / students.size
``````

Awesome!

### How many are above average?

In order to do this, we can use the `filter {...}` function.

Similar to the `sumBy {...}`, this function takes in what some people call a predicate, which is an expression that returns a `Boolean` (`true` or `false`) value.

In our case it would look like this:

``````val aboveAverage = students.filter { it.score > average }
``````

But there's something in particular about `filter`, it will not return a single value. It will actually return a new array of `Students` whose scores are above average. But we just need to count how many there are.

Remember how we used the `students.size` property?

Oh yeeeeeaaaah!

We can also use it after the `filter` block:

``````val aboveAverage = students.filter { it.score > average }.size
``````

_Fantastic!

### How many are below average?

I think you might already know how to this one... As any good Software Developer, we can trust our natural instincts and just copy/paste the hell out of our previous code:

``````val belowAverage = students.filter { it.score < average }.size
``````

What did we have to change?

• `aboveAvereage` to `belowAverage`.
• The `>` operator for the `<` operator.

And that's it!

## The Final Test

Now we just need to give a try. But! we haven't done anything in order to display the results yet...

Let's fix that by adding this at the end:

``````println("With an average of \$average, there are \$aboveAverage students above average and \$belowAverage below it.")
``````

Great!

If you followed each step closely, you should have something like this:

``````fun main(args: Array<String>) {
val students = arrayOf(
Student("Chris", 80),
Student("Mark", 67),
Student("Joseph", 98),
Student("Carl", 74),
Student("Katherine", 86)
)

val average = calculateAverageScore(students)

val aboveAverage = students.filter { it.score > average }.size

val belowAverage = students.filter { it.score < average }.size

println("With an average of \$average, there are \$aboveAverage students above average and \$belowAverage below it.")
}

private fun calculateAverageScore(students: Array<Student>) = students.sumBy { it.score } / students.size
``````

And the output should be:

``````With an average of 81, there are 2 students above average and 3 below it.
``````

## Recap:

We avoided any regular loop by using the `filter` and `sumBy` Higher-Order Functions provided by the Kotlin Standard Library with the help of our custom made Lambda Expressions to make our code really clean and concise.

And these features are not just available for us in Kotlin, many other languages support this kind of functions, you just have to Google how to write them in each particular one of them, but they are really similar, so don't chu worry :)

_You can checkout the full sample project [here](https://github.com/chrisvasqm/look-ma-without-loops)_

qwewqa

I believe you may be able to use the count function instead of the filter function to directly get the result.

Christian Vasquez • Edited

Hmmm ðŸ¤”

I'll check it out and update the post!

EDIT:

You are totally right ðŸ˜²

The `filter` way:

``````val belowAverage = students.filter { it.score < average }.size
``````

The `count` way:

``````val belowAverage = students.count { it.score < average }
``````

ðŸŽ‰ðŸŽ‰ðŸŽ‰

Ben Sinclair

What happens when there are no students in the class that term?

Christian Vasquez

As it is right now, when the `calculateAverageScore()` function gets executed, since the `students.size` is zero, it will cause a `java.lang.ArithmeticException: / by zero` ðŸ’¥

To avoid this you can use average function from stdlib, so istead of this:

``````fun calculateAverageScore(students: Array<Student>) =
students.sumBy { it.score } / students.size
``````

You can write:

``````fun calculateAverageScore(students: Array<Student>) =
students.map { it.score }.average()
``````