0

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?

3 Answers 3

1

You could just use the spread operator which "flattens" the object's properties.

const expectedStructure = { ...products, orders }
Sign up to request clarification or add additional context in comments.

Comments

1
const data = {
    products: ProductModel[],
    orders: OrderModel[]
}

const {products, orders} = data;

const expectedStructure = {
   ...products,
   orders,
}

checkout: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

checkout: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

Comments

0

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));

9 Comments

and if I know that the order can only be of one product, it would be better if after order filter, remove them from data?
@EmiliBellotPulido You can but GC (Garbage Collector) will do the work for you, for things that are not global you dont really need to worry about. It is if you are worried about your data object. if you are worried about results - you can just add .filter(x => x.orders.length > 0) after .map operator. But i could misunderstood you, sorry.
@EmiliBellotPulido Provide me some example and i will clarify
Your answer is correct, but I am thinking that foreach product I have to filter every time the entire order array and, maybe, as I know that the orders correspons only to one product, it would be better if I only filter the remaining orders.
@EmiliBellotPulido You have a good ideas but modifying array itself is also costly and it basically depends on how much items you have in the arrays. For something that is below 100 - i would not even bother with that. But if you are curious - someone already tried and measured your idea: medium.com/@justintulk/…
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.