ESP32 cpplinq: Filtering arrays of objects

In this tutorial we will learn how to filter an array of objects using cpplinq. The tests shown on this tutorial were performed using an ESP32 board from DFRobot.

Introduction

In this tutorial we will learn how to filter an array of objects using cpplinq, running on an ESP32.

On previous tutorials we have covered the use of many cpplinq operators for simple use cases, more precisely, to process arrays of integers. Nonetheless, the usefulness of this library is more evident when we use it for more complex use cases, such as processing arrays of objects.

Thus, in this tutorial, we will check how we can use cpplinq to filter an array of objects from a testing class. Our class will be very simple and it will model a person that has an id and an age.

We will then build an array of these objects and filter it to obtain only the persons that have more than 40 years.

We will make use of the where operator for this filtering, which we have also already covered in the previous post. The working principle of this operator is the same when operating over an array of objects: it receives as input a function that is applied for each element of the array and it should return true if that element fills our filtering criteria, and false otherwise.

To illustrate that we can also chain operators when working with sequences of objects, we will then order the final sequence by the age of the persons.

The tests shown on this tutorial were performed using an ESP32 board from DFRobot.

The code

As we have been doing in the previous tutorials, we will start by including the cpplinq library and declaring the use of the cpplinq namespace.

#include "cpplinq.hpp"
   
using namespace cpplinq;

After that we will define a class called Person. For simplicity, we will keep the class declaration in the same file as the rest of the code.

As already mentioned, our class will have two integer members: an id and an age. The constructor for this class will assign values to these two members.

class Person{
  
  public:
  
    int id;
    int age;
    
    Person (int t_id, int t_age){
      id = t_id;
      age = t_age;
    }
};

Moving on to the Arduino setup, we will start by opening a serial connection, to later output the results of the program.

Serial.begin(115200);

After this we will declare an array with objects of class Person, some of them filling our age criteria and others not.

Person personArray[] = {
    Person(1,70),
    Person(2,14),
    Person(3,24),
    Person(4,30),
    Person(4,89),
    Person(5,50),
};

To start applying the cpplinq operators, we need to convert our array to a range object first, like we did in previous tutorials when using integer arrays. We do this by calling the from_array function, passing as input our array of persons.

from_array(personArray)

After this we will filter the range by applying the where operator. As input, we will pass a function that will implement the filtering criteria. This function will be executed for each element of the array and it should return a Boolean value indicating if that element fills the filtering criteria (true) or not (false).

The elements for which the function returns true (meet the filtering criteria) will be on the resulting range.

The function passed to the where operator will receive as input the Person object of the current iteration. This means that we have the whole Person object if we want to apply more complex conditions over its fields.

We will declare our function using the C++ lambda syntax. This makes the code more compact, since we avoid declaring a new named function to be used as input of each operator we use.

When declaring the argument of our lambda (a Person object), we will specify it as const, so we don’t accidentally change its content on the function body. If so, the compiler will raise an error.

The function implementation will just consist on comparing the age with the value 40 and returning true if the age is greater, and false otherwise.

 where([](const Person p){return p.age > 40;})

Just to illustrate the chaining of cpplinq operators, we will now order our results with a call to the orderby operator. In this case, since we are operating over an array of objects, we need to indicate the field over which the ordering should be done. This is also specified by passing a function as input of the orderby operator.

This function is applied to all the elements of the array and thus, as before, it receives as input the Person object of the current iteration. It should return as output the value that will be used as ordering criteria. In our case, we will return the age of the Person.

As shown below, we will again use the C++ lambda syntax.

orderby([](const Person p){return p.age;})

After this we will convert the range to a C++ vector, so we can iterate it and print the results of the final sequence. The full expression tree can be seen below.

auto result = from_array(personArray)
               >> where([](const Person p){return p.age > 40;})
               >> orderby([](const Person p){return p.age;})
               >> to_vector();

To finalize, we will iterate over the vector and print the id and the age of the filtered and ordered array. We will use the printf function of the Serial object to make it easier to format the result.

for(int i=0; i<result.size(); ++i){
    Serial.printf("{id: %d age: %d}\n", result[i].id, result[i].age);
}

The final complete code can be seen below.

#include "cpplinq.hpp"
   
using namespace cpplinq;

class Person{
  
  public:
  
    int id;
    int age;
    
    Person (int t_id, int t_age){
      id = t_id;
      age = t_age;
    }
};

   
void setup() {
  Serial.begin(115200);
     
  Person personArray[] = {
    Person(1,70),
    Person(2,14),
    Person(3,24),
    Person(4,30),
    Person(4,89),
    Person(5,50),
  };
     
  auto result = from_array(personArray)
               >> where([](const Person p){return p.age > 40;})
               >> orderby([](const Person p){return p.age;})
               >> to_vector();
                  
  for(int i=0; i<result.size(); ++i){
    Serial.printf("{id: %d age: %d}\n", result[i].id, result[i].age);
  }
}
   
void loop() {}

Testing the code

To test the code, simply compile it and upload it to your ESP32 device, using the Arduino IDE. Once the procedure finishes, open the Arduino IDE serial monitor.

You should get an output similar to figure 1. As can be seen, only the Person objects with an age greater than 40 are printed, as expected. Additionally, the results are ordered by age.

Output of the project, showing the filtered and ordered list of objects.
Figure 1 – Output of the project, showing the filtered and ordered list of objects.

Leave a Reply

%d bloggers like this: