Issue
I am getting data from API structured like this:
interface ProductModel {
prod_id: string,
brand: string,
...
}
interface OrderModel {
order_id: string,
prod_id: string,
...
}
const data = {
products: ProductModel[],
orders: OrderModel[]
}
What I want is to restructure the data to group the orders of a product and the product info in one object:
const expectedStructure = {
prod_id: string,
brand: string,
...,
orders: OrderModel[]
}
I suppose that with a reduce it could be done easily, but I don't quite understand how it works. Could someone help me with this example?
Solution
Reduce can be used but you dont really need it, simple .map
with .filter
and ...
spread operator:
const products = [
{ prod_id: "1", brand: "brand1" },
{ prod_id: "2", brand: "brand1" },
{ prod_id: "3", brand: "brand2" },
{ prod_id: "4", brand: "brand2" },
{ prod_id: "5", brand: "brand3" }
];
const orders = [
{ order_id: "1", prod_id: "1" },
{ order_id: "2", prod_id: "2" },
{ order_id: "3", prod_id: "3" },
{ order_id: "4", prod_id: "3" },
{ order_id: "5", prod_id: "4" }
];
const data = {
products: products,
orders: orders
};
function groupData(data) {
if (!data) return data;
return data.products.map((p) => ({
...p,
orders: data.orders.filter((x) => x.prod_id === p.prod_id)
}));
}
console.log(groupData(data));
Adding a little optimization asked in comments using Map class. With that you will only need 1 loop over initial Orders
array to build the Map
object and then you will have a constant time of element retrieval:
const products = [
{ prod_id: "1", brand: "brand1" },
{ prod_id: "2", brand: "brand1" },
{ prod_id: "3", brand: "brand2" },
{ prod_id: "4", brand: "brand2" },
{ prod_id: "5", brand: "brand3" }
];
const orders = [
{ order_id: "1", prod_id: "1" },
{ order_id: "2", prod_id: "2" },
{ order_id: "3", prod_id: "3" },
{ order_id: "4", prod_id: "3" },
{ order_id: "5", prod_id: "4" }
];
const data = {
products: products,
orders: orders
};
function buildMap(data) {
const res = new Map();
data.orders.forEach((order) => {
if (res.has(order.prod_id)) {
res.get(order.prod_id).push(order);
} else {
res.set(order.prod_id, [order]);
}
});
return res;
}
function groupData(data) {
if (!data) return data;
const ordersMap = buildMap(data);
return data.products.map((p) => ({
...p,
orders: ordersMap.get(p.prod_id) || []
}));
}
console.log(groupData(data));
Answered By - Sergey Sosunov
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.