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.