2

I have an array of objects with nested category objects (see below). I would like to remove the duplicate objects (based on "objectID") and create a new array with only the objects that have a higher amount of nested "hierarchicalCategories" key value pairs

const objectsArray = [

{
  "objectID": 1234,
  "hierarchicalCategories": {
    "lvl0": "Women's",
    "lvl1": "Women's > Shirts",
    "lvl2": "Women's > Shirts > Tees"
  }
},
{
  "objectID": 5678,
  "hierarchicalCategories": {
    "lvl0": "Men's"
  }
},
{
  "objectID": 1234,
  "hierarchicalCategories": {
    "lvl0": "Women's"
  }
},
{
  "objectID": 5678,
  "hierarchicalCategories": {
    "lvl0": "Men's",
    "lvl1": "Men's > Shoes"
  }
}

]

So the expected result would look like this: The final array would filter duplicates and keep one instance of each object...the "objectID" : 1234 instance which had "hierarchicalCategories" up to "lvl2" and the "objectID" : 5678 instance which had "hierarchicalCategories" up to "lvl1"

const newArray = [

{
  "objectID": 1234,
  "hierarchicalCategories": {
    "lvl0": "Women's",
    "lvl1": "Women's > Shirts",
    "lvl2": "Women's > Shirts > Tees"
  }
},
{
  "objectID": 5678,
  "hierarchicalCategories": {
    "lvl0": "Men's",
    "lvl1": "Men's > Shoes"
  }
}

]

I have this function which works for a new array based on filtering duplicate objectID's, but I am not sure how to create logic to keep the object with more "hierarchicalCategories" key value pairs.

     const newArray = Array.from(new Set(objectsArray.map(a => a.objectID)))
                .map(objectID => {
                    return objectsArray.find(a => a.objectID === objectID)
         })
2
  • what does not work? please add your code. Commented Dec 24, 2019 at 16:53
  • @NinaScholz I updated my answer to include a function I am using to filter out duplicate objectID's but I am not sure how to approach filtering based on number of "hierarchicalCategories" in the nested object Commented Dec 24, 2019 at 17:01

4 Answers 4

3

You could take a Map and assign the categories to the same group.

const
    objectsArray = [{ objectID: 1234, hierarchicalCategories: { lvl0: "Women's", lvl1: "Women's > Shirts", lvl2: "Women's > Shirts > Tees" } }, { objectID: 5678, hierarchicalCategories: { lvl0: "Men's" } }, { objectID: 1234, hierarchicalCategories: { lvl0: "Women's" } }, { objectID: 5678, hierarchicalCategories: { lvl0: "Men's", lvl1: "Men's > Shoes" } }],
    result = Array.from(objectsArray
        .reduce((m, o) => {
            if (m.has(o.objectID)) {
                Object.assign(m.get(o.objectID).hierarchicalCategories, o.hierarchicalCategories);
                return m;
            }
            return m.set(o.objectID, o);            
        }, new Map)
       .values()
    );

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

A shorter approach by collecting the categroies directly and building new object from the collected parts.

const
    objectsArray = [{ objectID: 1234, hierarchicalCategories: { lvl0: "Women's", lvl1: "Women's > Shirts", lvl2: "Women's > Shirts > Tees" } }, { objectID: 5678, hierarchicalCategories: { lvl0: "Men's" } }, { objectID: 1234, hierarchicalCategories: { lvl0: "Women's" } }, { objectID: 5678, hierarchicalCategories: { lvl0: "Men's", lvl1: "Men's > Shoes" } }],
    result = Array.from(
        objectsArray.reduce((m, { objectID: id, hierarchicalCategories: o }) => 
            m.set(id, Object.assign((m.get(id) || {}), o)), new Map),
       ([objectID, hierarchicalCategories]) => ({ objectID, hierarchicalCategories })
    );

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

Sign up to request clarification or add additional context in comments.

Comments

3

Use .sort() and .filter() to sort from highest amount of levels to lowest and to filter so only the highest amount of levels is in the new array.

const objectsArray = [

  {
    "objectID": 1234,
    "hierarchicalCategories": {
      "lvl0": "Women's",
      "lvl1": "Women's > Shirts",
      "lvl2": "Women's > Shirts > Tees"
    }
  },
  {
    "objectID": 5678,
    "hierarchicalCategories": {
      "lvl0": "Men's"
    }
  },
  {
    "objectID": 1234,
    "hierarchicalCategories": {
      "lvl0": "Women's"
    }
  },
  {
    "objectID": 5678,
    "hierarchicalCategories": {
      "lvl0": "Men's",
      "lvl1": "Men's > Shoes"
    }
  }
]
const newArray = objectsArray.sort((a, b) => Object.keys(b.hierarchicalCategories).length - Object.keys(a.hierarchicalCategories).length).filter((v, i, a) => i === a.findIndex(e => e.objectID === v.objectID));

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

Comments

1
const shouldAdd = (item, target) => {
  if (!target[item.objectID]) return true;
  if (target[item.objectID] && !target[item.objectID].hierarchicalCategories && item.hierarchicalCategories) return true;
  if (target[item.objectID] && target[item.objectID].hierarchicalCategories && item.hierarchicalCategories && Object.keys(target[item.objectID].hierarchicalCategories).length < Object.keys(item.hierarchicalCategories).length) return true;
}

let newObjectsArray = {}
objectsArray.forEach((obj) => {
  if (shouldAdd(obj, newObjectsArray)) {
    newObjectsArray[obj.objectID] = obj
  }
})

console.log(Object.values(newObjectsArray)); //Object.values(newObjectsArray) should contain what you want 



Comments

1

const objectsArray = [

{
  "objectID": 1234,
  "hierarchicalCategories": {
    "lvl0": "Women's",
    "lvl1": "Women's > Shirts",
    "lvl2": "Women's > Shirts > Tees"
  }
},
{
  "objectID": 5678,
  "hierarchicalCategories": {
    "lvl0": "Men's"
  }
},
{
  "objectID": 1234,
  "hierarchicalCategories": {
    "lvl0": "Women's"
  }
},
{
  "objectID": 5678,
  "hierarchicalCategories": {
    "lvl0": "Men's",
    "lvl1": "Men's > Shoes"
  }
}

]

var result_arr = objectsArray.reduce((acc, curr) => {
    const existing_obj = acc.find(item => item.objectID === curr.objectID);
    if (existing_obj) {
        if (Object.keys(curr.hierarchicalCategories).length > Object.keys(existing_obj.hierarchicalCategories).length)
        existing_obj.hierarchicalCategories = {...curr.hierarchicalCategories };
    } else {
        acc.push(curr);
    }
    return acc;
}, []);

console.log(result_arr)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.