How to remove duplicate category from array of objects?

Viewed 47

i had array of objects and in each object had category and if any duplicate category is there i have to show only one object.

Here is my array.

 const costItems= [
    {
     
      amount: 1000,
      category: 'Appliances',
      instructions: '',
      subcontractor: [Object],
      thresholdAmount: null,
      thresholdPercent: null
    },
    {
      
      amount: 500,
      category: 'Appliances',
      instructions: '',
      subcontractor: [Object],
      thresholdAmount: null,
      thresholdPercent: null
    },
    {
      
      amount: null,
      category: 'Appraisal',
      instructions: '',
      subcontractor: [Object],
      thresholdAmount: null,
      thresholdPercent: null
    },
    {
     
      amount: null,
      category: 'Building Permit',
      instructions: '',
      subcontractor: [Object],
      thresholdAmount: null,
      thresholdPercent: null
    }
  ]

How can i remove duplicate category from array of objects ?

3 Answers

You can try any one of the loop methods.

Array.reduce method implementation.

const costItems = [
  { amount: 1000, category: "Appliances", instructions: "", subcontractor: [], thresholdAmount: null, thresholdPercent: null },
  { amount: 500, category: "Appliances", instructions: "", subcontractor: [], thresholdAmount: null, thresholdPercent: null },
  { amount: null, category: "Appraisal", instructions: "", subcontractor: [], thresholdAmount: null, thresholdPercent: null },
  { amount: null, category: "Building Permit", instructions: "", subcontractor: [], thresholdAmount: null, thresholdPercent: null },
];
const uniqueArray = costItems.reduce((acc, curr) => {
  const matchNode = acc.find((item) => item.category === curr.category);
  if (!matchNode) {
    acc.push(curr);
  }
  return acc;
}, []);
console.log(uniqueArray);

Assuming your data is sorted alphabetically in ascending order (A -> Z) you can use the following algorithm which will run in O(n) time and therefore be faster than any solution using find() or indexOf() which will result in a runtime of O(n^2). This solution always keeps the last occurrence. A similar solution can be constructed if you want to keep the first occurence.

The idea is to always remember the last index we have encountered for a given value in your case for category. Once we encounter a new value, we use that index to get the previous value which is (due to sorted order) guaranteed to be the last of all occurences.

const costItems= [
    {
     
      amount: 1000,
      category: 'Appliances',
      instructions: '',
      subcontractor: "Appliance last occurrence",
      thresholdAmount: null,
      thresholdPercent: null
    },
    {
      
      amount: 500,
      category: 'Appliances',
      instructions: '',
      subcontractor: "Appliance last occurrence",
      thresholdAmount: null,
      thresholdPercent: null
    },
    {
      
      amount: null,
      category: 'Appraisal',
      instructions: '',
      subcontractor: "Appliance first and last occurrence",
      thresholdAmount: null,
      thresholdPercent: null
    },
    {
     
      amount: null,
      category: 'Building Permit',
      instructions: '',
      subcontractor: "Appliance first and last occurrence",
      thresholdAmount: null,
      thresholdPercent: null
    }
  ]
  
  function removeDuplicatesKeepLastOccurrence(items, key){
    if(items.length < 2) return items.slice();
    let prev = 0;
    const result = [];
    items.forEach((value, i, items) => {
      if(items[prev][key] !== value[key]) result.push(items[prev])
      prev = i;
    })
    result.push(items[items.length - 1])
    return result;
  }
  
  console.log(removeDuplicatesKeepLastOccurrence(costItems, "category"))

I've marked the occurences with first or last so you can clearly see that only the last occurences are within the result.

One-liner if you don't mind

const data = [{amount:1000,category:"Appliances",instructions:"",subcontractor:[],thresholdAmount:null,thresholdPercent:null},{amount:500,category:"Appliances",instructions:"",subcontractor:[],thresholdAmount:null,thresholdPercent:null },{amount:null,category:"Appraisal",instructions:"",subcontractor:[],thresholdAmount:null,thresholdPercent:null},{amount:null,category:"Building Permit",instructions:"",subcontractor:[],thresholdAmount:null,thresholdPercent:null}];

const result = Object.values(data.reduce((r, o) => (r[o.category] ??= o, r), {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }

Related