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.

asked Nov 11, 2020 at 5:31
\$\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));

answered Nov 11, 2020 at 6:25
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.