1
\$\begingroup\$

I have two arrays of objects. One has an id property with a list of ids and the second has an object with a unique id property. I want to filter the ids in the second array with the first list and get the data.

const data1 = [{
  name: 'A',
  ids: [1, 2, 3]
}, {
  name: 'B',
  ids: [4, 5, 6]
}, {
  name: 'C',
  ids: [7, 8, 9]
}]

const data2 = [{
    id: 1,
    color: 'red'
  }, {
    id: 2,
    color: 'black'
  }, {
    id: 3,
    color: 'blue'
  }, {
    id: 4,
    color: 'yellow'
  }, {
    id: 5,
    color: 'green'
  }, {
    id: 6,
    color: 'pink'
  },
  {
    id: 7,
    color: 'orange'
  }, {
    id: 8,
    color: 'white'
  }, {
    id: 9,
    color: 'teal'
  }
]

const arrayToObject = (array) =>
  array.reduce((obj, item) => {
    obj[item.id] = item
    return obj
  }, {})

console.log(arrayToObject(data2))

const newData = data1.map(item => {
  return {
    name: item.name,
    data: item.ids.map(i => arrayToObject(data2)[i])
  }
})

console.log(newData)

Expected Output:

[
  {
    "name": "A",
    "data": [
      {
        "id": 1,
        "color": "red"
      },
      {
        "id": 2,
        "color": "black"
      },
      {
        "id": 3,
        "color": "blue"
      }
    ]
  },
  {
    "name": "B",
    "data": [
      {
        "id": 4,
        "color": "yellow"
      },
      {
        "id": 5,
        "color": "green"
      },
      {
        "id": 6,
        "color": "pink"
      }
    ]
  },
  {
    "name": "C",
    "data": [
      {
        "id": 7,
        "color": "orange"
      },
      {
        "id": 8,
        "color": "white"
      },
      {
        "id": 9,
        "color": "teal"
      }
    ]
  }
]

I did manage to achieve this, but I guess there might be a better clean and performant solution. Please advice me on that.

P.S: I am also open to using lodash.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Use Map to reduce search complexity

Currently your method is rather complex at \$O(n^2)\$. The reason is that for each Id you iterate each item to locate the one with the Id you want.

You can use a Map to reduce the complexity. Map uses a hash to locate items, you can add each id to a map linking ids to each category.

Then just iterate the items array using the map to locate the correct category and add the item.

The result is achieved in a time complexity of \$O(n)\$.

The example shows how this can be implemented.

const categories = [{name: 'A', ids: [1, 2, 3]}, {name: 'B', ids: [4, 5, 6]}, {name: 'C', ids: [7, 8, 9]}]
const items = [{ id: 1, color: 'red'}, { id: 2, color: 'black'}, { id: 3, color: 'blue'}, { id: 4, color: 'yellow'}, { id: 5, color: 'green'}, { id: 6, color: 'pink'},{ id: 7, color: 'orange'}, { id: 8, color: 'white'}, { id: 9, color: 'teal'}];


function categorizeById(cats, items) {
    const idMap = new Map();
    const result = cats.map(cat => {
        const category = {name: cat.name, data: []};
        cat.ids.forEach(id => idMap.set(id, category));
        return category ;
    },[]);
    items.forEach(item => idMap.get(item.id).data.push({...item}));
    return result;
}
console.log(categorizeById(categories, items));

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.