Efficient Order Organization with JavaScript: Unleash the Power of map, filter, and reduce
In this comprehensive guide, we’ll embark on a journey to harness the power of JavaScript’s array manipulation methods — map
, filter
, and reduce
. Our mission? To expertly organize orders, grouping them by the market while gracefully excluding any cancelled orders. These array methods will be invaluable allies in our quest for efficient and maintainable code.
Throughout this blog, we’ll explore three distinct techniques, each artfully utilizing a combination of map
, filter
, and reduce
functions. We’ll provide code examples that break down the process of organizing orders step by step, shining a spotlight on the advantages and considerations of each approach.
By the end of this journey, you’ll emerge with a profound understanding of how to wield map
, filter
, and reduce
methods in JavaScript to streamline order organization. Armed with this knowledge, you’ll confidently choose the most fitting technique for your future projects.
Before we begin our journey, check out this tweet from Steven Luscher and understand the basics:
In JavaScript, map
, filter
, and reduce
are higher-order functions that operate on arrays and return new arrays as a result. These functions are typically used in an immutable way, meaning that they do not modify the original array but instead create a new array with the desired changes. Here’s a brief explanation for each:
1. map
: The map
function creates a new array by applying a given function to each element of the original array. It does not modify the original array.
const originalArray = [1, 2, 3];
const newArray = originalArray.map(x => x * 2);
// originalArray is still [1, 2, 3], and newArray is [2, 4, 6]
2. filter
: The filter
function creates a new array containing elements from the original array that satisfy a certain condition. It also does not modify the original array.
const originalArray = [1, 2, 3, 4, 5];
const filteredArray = originalArray.filter(x => x % 2 === 0);
// originalArray is still [1, 2, 3, 4, 5], and filteredArray is [2, 4]
3. reduce
: The reduce
function iteratively combines elements of an array into a single value. It also does not modify the original array.
const originalArray = [1, 2, 3, 4, 5];
const sum = originalArray.reduce((acc, current) => acc + current, 0);
// originalArray is still [1, 2, 3, 4, 5], and sum is 15
In all these cases, the original arrays remain unchanged, and new arrays or values are produced. This immutability is a fundamental concept in functional programming and helps prevent unintended side effects in your code. However, if you wish to modify the original array, you can do so explicitly, but it’s generally considered good practice to use these functions in an immutable manner.
Let’s embark on our crypto-enlightening expedition!
Using map:
The map
method is our first stop on this journey. It empowers us to transform and manipulate elements within an array, crafting a new array enriched with modified values. One crucial distinction: map
preserves the original array’s length throughout the operation.
Let’s embark on a step-by-step exploration with a practical example. We have a collection of crypto orders, each tagged with a market
field representing a cryptocurrency code (e.g., “wrxinr” for Wazir X Token). Our task is to replace these codes with their corresponding names.
const orders = [
{
id: 1143081608,
ord_type: "limit",
market: "wrxinr",
price: "111.71",
state: "completed"
},
{
id: 1143035555,
ord_type: "limit",
market: "shibinr",
price: "0.000544",
state: "closed"
}
]
To achieve this, we’ll iterate through each order and perform the necessary market value replacement:
const coinNames = {
wrxinr: 'WazirX Token (WRX)',
shibinr: 'SHIBA INU (SHIB)'
}
const transformedOrders = orders.map((order) => ({
...order,
market: coinNames[order.market]
}))
The result? An array of transformed orders with market names replacing codes:
[
{
id: 1143081608,
ord_type: "limit",
market: "WazirX Token (WRX)",
price: "111.71",
state: "completed"
},
{
id: 1143035555,
ord_type: "limit",
market: "SHIBA INU (SHIB)",
price: "0.000544",
state: "closed"
}
]
Utilizing filter:
Our next destination is the realm of filter
. This method excels at extracting elements from an array based on specific criteria, producing a fresh array containing only those that meet our conditions.
Consider our collection of market orders once more. This time, we aim to isolate the completed orders, filtering out the rest.
const completedOrders = orders.filter((order) => order.status === 'completed');
Combining map and filter:
What if we seek to perform both the market value replacement and the filtering of completed orders in a single operation? This is where the reduce
method comes to our aid.
However, we must note that the initial code combining map
and filter
results in two iterations over the orders as below example.
const completedOrders = orders.filter(order => order.status === 'completed')
.map(order => ({...order, market: coinNames[order.market]}))
Let’s refactor it to accomplish the same goal with a single operation — enter the reduce
method.
const completedOrders = orders.reduce((acc, order) => {
if (order.status === 'completed') {
return [...acc, {...order, market: coinNames[order.market]}]
}
return acc
}, [])
The result mirrors our previous approach, combining mapping and filtering efficiently in one go:
[
{
id: 1143081608,
ord_type: "limit",
market: "WazirX Token (WRX)",
price: "111.71",
state: "completed"
}
]
You’ll notice the reduce
method at play in this refactored code. It comes equipped with two essential components:
1. A callback function invoked for each array element, equipped with two parameters — acc (the accumulator, representing the previous value) and order. The accumulator starts with the initial value specified as the second argument.
2. An initial value for the accumulator — in our code, it’s an empty array [].
Grouping Orders by Status:
Another important enhancement we’ll make is grouping the cryptocurrency orders based on their status. Instead of simply filtering orders by their completion status (e.g., completed or pending), we’ll create distinct groups for each status. This approach provides a more insightful view of how orders are distributed among various states.
const ordersByGroup = [...cryptoOrders].reduce((acc, o) => {
const order = { ...o, market: coinNames[o.market] };
const isStatePresent = !!acc[order.state];
const ordersByState = isStatePresent
? [...acc[order.state], order]
: [order];
return {
...acc,
[order.state]: ordersByState
};
}, {})
By utilizing the reduce
method, we accumulate orders into different groups based on their status. This results in a structured data format that offers a clear overview of how orders are distributed among various states, making it easier to analyze and manage them effectively.
Please check the complete solution in the sandbox.
Conclusion:
In the world of development, the ability to select the right tool for the job is indispensable. When considering complexity and project requirements, one of these techniques may shine brighter than the others. Keep code readability, performance, and maintainability in mind when making your choice.
In summary, map
, filter
, and reduce
are not mere methods, they are mighty instruments in your JavaScript arsenal. By comprehending their capabilities and the scenarios in which to deploy them, you’ll craft cleaner, more efficient code. Armed with these techniques, you can navigate data manipulation tasks with confidence.
Additional Resources:
- MDN Web Docs: Array.prototype.map()
- MDN Web Docs: Array.prototype.filter()
- MDN Web Docs: Array.prototype.reduce()
With these methods at your fingertips and a firm grasp of their optimal application, you’re primed to conquer a diverse array of data organization and manipulation challenges in your JavaScript projects. Happy coding! ⌨️