Data Manipulation with a`transformArray` Function
Hey fellow developers! Ever found yourself needing to group, filter, and aggregate array data in a specific way? Maybe you want to calculate the average price of in-stock items per category, or count the number of active users based on some criteria. If you've been writing repetitive filter, reduce, and looping logic, I've got something that might just become your new best friend: a versatile transformArray function. Let's dive in and see how it can supercharge your data wrangling! The Problem: Tedious Array Transformations Imagine you have an array of product objects like this: const input = [ { id: 1, category: 'electronics', price: 500, inStock: true }, { id: 2, category: 'books', price: 200, inStock: true }, { id: 3, category: 'electronics', price: 1500, inStock: false }, { id: 4, category: 'books', price: 350, inStock: true } ]; Now, say you want to get a summary of the in-stock items, grouped by category, showing the total number of items and their average price. Without a dedicated function, you might end up with something like this: const inStockItems = input.filter(item => item.inStock); const electronics = inStockItems.filter(item => item.category === 'electronics'); const books = inStockItems.filter(item => item.category === 'books'); const electronicsSummary = { totalItems: electronics.length, averagePrice: electronics.reduce((sum, item) => sum + item.price, 0) / electronics.length }; const booksSummary = { totalItems: books.length, averagePrice: books.reduce((sum, item) => sum + item.price, 0) / books.length }; const result = { electronics: electronicsSummary, books: booksSummary }; console.log(result); This works, but it's a bit verbose and doesn't scale well if you have more categories or different aggregation needs. This is where our transformArray function shines! The Solution: A Flexible transformArray Function Here's the transformArray function that aims to simplify these kinds of transformations: function transformArray(arr, key, filterFn, aggregateFn) { let res = {}; for (let i = 0; i

Hey fellow developers! Ever found yourself needing to group, filter, and aggregate array data in a specific way? Maybe you want to calculate the average price of in-stock items per category, or count the number of active users based on some criteria.
If you've been writing repetitive filter
, reduce
, and looping logic, I've got something that might just become your new best friend: a versatile transformArray
function. Let's dive in and see how it can supercharge your data wrangling!
The Problem: Tedious Array Transformations
Imagine you have an array of product objects like this:
const input = [
{ id: 1, category: 'electronics', price: 500, inStock: true },
{ id: 2, category: 'books', price: 200, inStock: true },
{ id: 3, category: 'electronics', price: 1500, inStock: false },
{ id: 4, category: 'books', price: 350, inStock: true }
];
Now, say you want to get a summary of the in-stock items, grouped by category, showing the total number of items and their average price. Without a dedicated function, you might end up with something like this:
const inStockItems = input.filter(item => item.inStock);
const electronics = inStockItems.filter(item => item.category === 'electronics');
const books = inStockItems.filter(item => item.category === 'books');
const electronicsSummary = {
totalItems: electronics.length,
averagePrice: electronics.reduce((sum, item) => sum + item.price, 0) / electronics.length
};
const booksSummary = {
totalItems: books.length,
averagePrice: books.reduce((sum, item) => sum + item.price, 0) / books.length
};
const result = { electronics: electronicsSummary, books: booksSummary };
console.log(result);
This works, but it's a bit verbose and doesn't scale well if you have more categories or different aggregation needs. This is where our transformArray
function shines!
The Solution: A Flexible transformArray
Function
Here's the transformArray
function that aims to simplify these kinds of transformations:
function transformArray(arr, key, filterFn, aggregateFn) {
let res = {};
for (let i = 0; i < arr.length; i++) {
if (!filterFn(arr[i])) continue;
const groupKey = arr[i][key];
if (!res[groupKey]) res[groupKey] = [];
res[groupKey] = [...res[groupKey], arr[i]];
}
for (const key in res) {
res[key] = aggregateFn(res[key]);
}
return res;
}
Let's break down what's happening here:
-
arr
: The input array you want to transform. -
key
: The property name to group the array elements by (e.g., 'category'). -
filterFn
: A function that takes an item from the array as input and returns true if the item should be included in the transformation, and false otherwise. -
aggregateFn
: A function that takes an array of grouped items as input and returns the aggregated result for that group (e.g., an object withtotalItems
andaveragePrice
).
Putting transformArray
to Work
Now, let's see how we can use our transformArray
function to achieve the same result as our previous verbose code:
const result = transformArray(
input,
'category',
(item) => item.inStock,
(group) => ({
totalItems: group.length,
averagePrice: group.reduce((sum, item) => sum + item.price, 0) / group.length
})
);
console.log(result);
// Output:
// {
// electronics: { totalItems: 1, averagePrice: 500 },
// books: { totalItems: 2, averagePrice: 275 }
// }
Isn't that much cleaner and more expressive? We've encapsulated the grouping, filtering, and aggregation logic into a single, reusable function call.
The Power of Flexibility: Beyond Simple Aggregation
The beauty of transformArray
lies in its flexibility. You can easily adapt it to perform various transformations by simply changing the filterFn
and aggregateFn
.
Example 1: Counting Items Per Category (Regardless of Stock)
const categoryCounts = transformArray(
input,
'category',
() => true, // Include all items
(group) => ({ count: group.length })
);
console.log(categoryCounts);
// Output:
// {
// electronics: { count: 2 },
// books: { count: 2 }
// }
Example 2: Finding the Most Expensive In-Stock Item Per Category
const mostExpensiveInStock = transformArray(
input,
'category',
(item) => item.inStock,
(group) => group.reduce((max, item) => (item.price > max.price ? item : max), group[0] || {})
);
console.log(mostExpensiveInStock);
// Output:
// {
// electronics: { id: 1, category: 'electronics', price: 500, inStock: true },
// books: { id: 4, category: 'books', price: 350, inStock: true }
// }
Example 3: Checking if All Items in a Category Are In Stock
const allInStockByCategory = transformArray(
input,
'category',
() => true,
(group) => ({ allInStock: group.every(item => item.inStock) })
);
console.log(allInStockByCategory);
// Output:
// {
// electronics: { allInStock: false },
// books: { allInStock: true }
// }
As you can see, by providing different filtering and aggregation functions, transformArray can handle a wide range of data manipulation tasks.
Conclusion: Embrace Reusability and Clarity
The transformArray
function provides a clean and reusable way to perform common data manipulation tasks in JavaScript. By abstracting the grouping, filtering, and aggregation logic, you can write more readable, maintainable, and flexible code. Happy coding!