Stop using for loops and start showing intent

rocksheep

Marinus van Velzen

Posted on February 28, 2023

Stop using for loops and start showing intent

Over the years I keep seeing people abuse the very popular for loops. This powerful tool allows you to go over entire lists of items and do things with them. The biggest downside to these is that need to read the entire loop in order to discover what it does. Luckily most programming languages these days provide multiple functions that you can apply to your lists and/or arrays of data to get the same results, but with shown intent!

In this article I will show you the most used functions and how they work with the help of PHP.

Before we start

Before we start I will set up a small amount of classes and variables that will be used as examples further into the article.

class Movie {
    public function __construct(
        public string $title,
        public string $genre,
        public int $rating
    ) {}
}

$moviesAsJson = [
    [
        'title' => 'John Wick',
        'genre' => 'action',
        'rating' => 86,
    ],
    [
        'title' => 'Frozen',
        'genre' => 'kids&family',
        'rating' => 90,
    ],
    [
        'title' => 'Hot Fuzz',
        'genre' => 'action',
        'rating' => 91,
    ],
    [
        'title' => 'Scott Pilgrim vs. the World',
        'genre' => 'comedy',
        'rating' => 82,
    ],
];
Enter fullscreen mode Exit fullscreen mode

Examples of the functions

The examples given in this section will probably be of the same length of code as the examples while using foreach loops, so you will probably think that these functions are not very special.

Keep in mind that the actual code will almost always be longer, so you will need to read the entire foreach loop to see what the intention of the writer was. To keep the code simple I chose to use short examples.

Transforming data

Let's start with one of the functions I use the most. It's the map function. This function is used to transform data in an array to something completely different. We will use the result of this transformation in the following examples.

$movies = []
foreach ($moviesAsJson as $movie) {
    $movies[] = new Movie(
        $movie['title'],
        $movie['genre'],
        $movie['rating']
    );
}

$movies = array_map(
    fn (array $movie) => new Movie(
        $movie['title'],
        $movie['genre'],
        $movie['rating']
    ),
    $moviesAsJson,
);
Enter fullscreen mode Exit fullscreen mode

Filtering

Sometimes you might even need to filter data from an array. Let's say I only want a list of action movies. If you don't use array methods you will write something like this.

$actionMovies = []
foreach ($movies as $movie) {
    if ($movie->genre === 'action') {
        $actionMovies[] = $movie;
    }
}
Enter fullscreen mode Exit fullscreen mode

This can be made a lot more clear if you use the filter method.

$actionMovies = array_filter(
    $movies,
    fn (Movie $movie) => $movie->genre === 'action'
);
Enter fullscreen mode Exit fullscreen mode

Reducing array to a new value

The reduce method usually is one of the more confusing ones in the entire suite. It is used to reduce an entire array to a single value. To demonstrate the power of this method I will give two examples.

First I want the movies to be grouped by genre. This way I can easily display the movies in their own sections without having to use an array_filter!

$moviesByGenre = [];
foreach ($movies as $movie) {
    $moviesByGenre[$movie->genre] ??= [];
    $moviesByGenre[$movie->genre][] = $movie;
}
Enter fullscreen mode Exit fullscreen mode

Now this is what it would look like using the reduce function.

$moviesByGenre = array_reduce(
    $movies,
    function (array $moviesByGenre, Movie $movie) {
        $moviesByGenre[$movie->genre] ??= [];
        $moviesByGenre[$movie->genre][] = $movie;

        return $moviesByGenre;
    },
    []
);
Enter fullscreen mode Exit fullscreen mode

Another usual use of the reduce function is to calculate values. Let's say we want the average rating of the given movies.

$totalRating = 0;

foreach ($movies as $movie) {
    $totalRating += $movie->rating;
}

$averageRating = $totalRating / count($movies);
Enter fullscreen mode Exit fullscreen mode

This is what it would look like using array reduce

$totalRating = array_reduce(
    $movies,
    fn (int $totalRating, Movie $movie) => $totalRating + $movie->rating,
    0
);

$averageRating = $totalRating / count($movies);
Enter fullscreen mode Exit fullscreen mode

Conclusion

The array functions allow the reader to instantly read the intent of what you want to do with your array. They won't have to sift through the entire foreach loop and thus they can immediately focus on whats being altered/filtered/reduced.

💖 💪 🙅 🚩
rocksheep
Marinus van Velzen

Posted on February 28, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related