Filter, Map and Reduce Operations


Performance, fast and practical code development with Filter, Map and Reduce operations.


Let's understand these operations by giving an example of making pizza.

To make a pizza we need to use many ingredients. Well, what materials are we going to use, the arrayFilter function does this, that is, it extracts what we need from all the data we have. So, we need a filter function to find the flour, salt, oil, tomato sauce, cheese, garlic, onion, oregano, and yeast we will use for our pizza. Now we have the materials. So, do we put them in an oven and wait for them to cook? No, we definitely need to prepare the flour, chop the tomatoes, garlic, cheese, and onions. For this, we need to use the array map function. The Map operation allows us to convert data to another type or result by processing it. In other words, operations such as chopping onions belong to the map function. If we consider this as data, we can say that the VAT amount we will find as a result of multiplying the VAT rate with the pure amount. In fact, the VAT amount is a result, not a value. Or data processed in rows such as row net sum should be processed with map. Yes, we have now processed what will be processed from our materials, so we cut the onions, tomatoes, and garlic. Now it's time for the cooking part. Reduce is the main thing to pay attention to here. Because the result of the reduce operation no longer reaches any of the original results. In other words, when we make pizza, we no longer call it made form of cheese, onion, and garlic, we call it pizza directly. Reduce produces a singular result on a data string. For example, we can say the sum of invoice lines. Sometimes it can also do grouping, for example, totals according to vat rates. Here, even if there is more than one data as a result of grouping, it is not possible to return to the main data, as a result, new data has been created. 

Preliminary information for functions starting with List and Array

If you see list and array prefixed functions with the same function postfix, choose the ones that start with array. For example, arrayFilter and listFilter functions filter on arrays and lists. But actually list is a virtual array. Each time, the list is converted to an array, and then the list is converted again. For this reason, even if the result will be used as a list, it should be executed over array, and if our initial value is list, it should be converted back to list after all operations are completed by converting to array with listToArray. It is necessary to convert lists to arrays each time and prevent the conversion of lists again. Therefore, our topic will be explained through functions with array prefixes.

arrayFilter(array, function(element [,index [,array]])) array

Filter function provides processing by sending all the elements in the array to the function given in the second parameter one by one. The elements of the array are passed to the function via the element variable, the sequence number on the index and the main index over the array variable. At least the element variable must be specified in the function to be written, other variables do not need to be specified.

It generally performs filtering by filtering the elements on an array. For example, it performs the process of finding invoices with the customer name "Halit". For this, if we want to select records with customer field "Halit" from an array called invoices, we can use it as follows.

It should be noted that all functions that return a boolean result can work for this operation. In other words, it is used in more complex operations such as those that are processed in the function block and the result exceeds a certain value. However, the point we should not forget is that if the value to be calculated and controlled in the filter can be used later, it would be appropriate to first calculate the data by mapping and then reduce it to the simple filter level. But if only the result of the calculation will be filtered, making a map may mean generating extra data. I would like to draw your attention to the fact that we did not reuse the index and the main array in this example.

arrayMap(array, function(element [,index [,array]])) array

The Map function provides a new value by sending all the elements in the array to the function given in the second parameter, one by one. The elements of the array are passed to the function via the element variable, the sequence number on the index and the main index over the array variable. At least the element variable must be specified in the function to be written, other variables do not need to be specified. The new value created here is added to the result array with the same index. The element to be added can be a new variable or a modified version of the existing variable.

It is generally used for operations that reach the result by calculating. As in the example I gave before, we can use it for operations such as finding the VAT amount by multiplying the total row total with the VAT rate. For example, let's have the total and vat fields in an array, and let's calculate and add the vat_amount field to this row.

In this example, the vat_amount field is calculated for each element in the invoice_rows array, added to the existing struct, and the existing and added struct is converted as a new value. The result is transferred to the same variable, which is done because it is the case that the same variable is modified (ie, existing values are not corrupted). It is reasonable to do it this way. However, if you are doing an operation that will make the elements in the array different from the old ones, assigning them to the old array variable may be a wrong move. For example, you can convert the values in TL in our array to USD and get them into a new array.

arrayReduce(array, function(result, element [, index [, array]]) [,initial_value]) any

The reduce function sends each element in the array to the function, assigns it to the result value and returns the result value as the result. Although this process is a bit confusing, we can actually compare the result of each row to the result value and call the function again with the final result value. 

It is often used in operations such as subtotals or aggregates by grouping. For example, let's find the sum of an invoice and the VAT totals according to the VAT rate.

In this example, both plain logic sums and grouping logics are summed. While the final result was reached by adding the result value each time in the flat sum, another struct was created and returned in the operation made by grouping. The point to be considered here is to set the result value with the initial value before starting the operations, since the initial_value does not always work stable.

Pipe operations

This concept is used for operations that try to produce results by working sequentially and nested together. For example, let's take the total VAT amount of the lines without promotions in the invoice lines.

You can call the filter map and reduce operation infinitely depending on the nested need, filter, calculate and re-filter according to the calculated field, create a grouped result, calculate it, filter this result and turn it into a result again. In other words, you can quickly make the codes what you want with this nested trio. Of course, you don't have to use all three, you can only meet your needs in a binary process like filter and map, or you can take hierarchical data like map and reduce to higher levels by calculating.

Appropriate Approach

Sir, you can say that we can calculate these operations, for example, while performing loop operations in tables, that is, while printing the fields on the screen. However, the important point is to separate the model and view from each other.

The purpose of the three important functions I have given in this topic and the other functions I have not given is to shape the model. In other words, other software developers will clearly understand the pipe operations you will do on the model and the calculations you make in the software developed in the community and the results will be at the model level, and they will know that there are no aggregate transactions hidden between html and other codes. If you can finish the process before output, when a new feature is added, you either open another node on the pipe or assign the necessary values to a new variable. The processes in the traditional loop process, called spaghetti, are difficult to understand, full of overlooked calculations, or codes that are risky and difficult to get in between. The clean code approach foresees that the model and view codes should be grouped as much as possible, isolated from each other, even if they are in the same file. In addition, these functions again minimize the code and eliminate the crowd of intermediate variables that will occur in the spaghetti process. I will explain in detail these functions, which can overcome some restrictions in the concept of query of query and can work together with query of query, in my article that will be published later.


Feedback

Did you find this content helpful?