Home > front end >  I want to combine the objects in the array, how should I change them?
I want to combine the objects in the array, how should I change them?

Time:05-15

const data = [
  {
    productId: 6,
    productName: "pouch",
    productPrice: 29000,
    discountRate: 19,
    optionName: "13inch",
    optionPrice: 0,
    qty: 2,
  },
  {
    productId: 6,
    productName: "pouch",
    productPrice: 29000,
    discountRate: 19,
    optionName: "15inch",
    optionPrice: 1000,
    qty: 1,
  },
]

const results = data.reduce((prev, curr) => {
  if (prev.productId === curr.productId) {
    ???
  }
  
}, []);

output

  {
    productId: 6,
    productName: "pouch",
    productPrice: 29000,
    discountRate: 19,
    option: [
      { optionName: "13inch", optionPrice: 0, qty: 2 },
      { optionName: "15inch", optionPrice: 1000, qty: 1 },
    ],
  },

If the productId is the same as the code above,

I want to remove the overlapping part of key:value, create an option object for the non-overlapping part, and create an array object for value.

I tried to solve it by using reduce, but it didn't go well, so I'm asking you a question.

CodePudding user response:

One method is to convert array into object, and use productId as key:

const data = [
  {
    productId: 6,
    productName: "pouch",
    productPrice: 29000,
    discountRate: 19,
    optionName: "13inch",
    optionPrice: 0,
    qty: 2,
  },
  {
    productId: 6,
    productName: "pouch",
    productPrice: 29000,
    discountRate: 19,
    optionName: "15inch",
    optionPrice: 1000,
    qty: 1,
  },
  {
    productId: 4,
    productName: "pouch",
    productPrice: 29000,
    discountRate: 19,
    optionName: "15inch",
    optionPrice: 1000,
    qty: 1,
  },
]

const results = Object.values(data.reduce((prev, curr) => {
  if (prev[curr.productId])
  {
    const obj = prev[curr.productId];
    if (!obj.option)
    {
      obj.option = [];
      obj.option.push({optionName: obj.optionName, optionPrice: obj.optionPrice, qty: obj.qty});
      delete obj.optionName;
      delete obj.optionPrice;
      delete obj.qty;
    }
    
    prev[curr.productId].option.push({optionName: curr.optionName, optionPrice: curr.optionPrice, qty: curr.qty});
  }
  else
    prev[curr.productId] = Object.assign({}, curr);

  return prev;
  
}, {}));

console.log(results);

CodePudding user response:

Here's a pure, functional approach which won't mutate any part of your existing array data:

function deduplicate (array) {
  const results = [];
  const idCache = new Set();

  for (const item of array) {
    // skip if we've already seen products with the same ID
    if (idCache.has(item.productId)) continue;
    idCache.add(item.productId);
    // get products with matching ID
    const items = array.filter(({productId}) => productId === item.productId);

    // if there were none, store the single product as-is and continue
    if (items.length === 0) {
      results.push({...item});
      continue;
    }

    // add initial product to others, preserving order
    items.unshift(item);
    const merged = {};

    for (const key of Object.keys(item)) {
      const values = items.map(item => item[key]);
      // if all the same value, set it on the merged object
      if (values.every(val => val === item[key])) merged[key] = item[key];
      else {
        // set to property on obj in "options" array
        for (const [idx, val] of values.entries()) {
          ((merged.options ??= [])[idx] ??= {})[key] = val;
        }
      }
    }

    results.push(merged);
  }

  return results;
}

const data = [
  {
    productId: 6,
    productName: "pouch",
    productPrice: 29000,
    discountRate: 19,
    optionName: "13inch",
    optionPrice: 0,
    qty: 2,
  },
  {
    productId: 6,
    productName: "pouch",
    productPrice: 29000,
    discountRate: 19,
    optionName: "15inch",
    optionPrice: 1000,
    qty: 1,
  },
  {
    productId: 5,
    productName: "pouch",
    productPrice: 29000,
    discountRate: 19,
    optionName: "15inch",
    optionPrice: 1000,
    qty: 1,
  },
];

const result = deduplicate(data);
console.log(result);

  • Related