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

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.