1

I was just wondering the best way to approach this in JavaScript using ES6.

Using the following data:

categories: [
    {id: 1,name: "category 1",items: [19993, 99737]},
    {id: 2,name: "category 2",items: [70264, 65474, 07078]},
    {id: 3,name: "category 3",items: [76765]}
]

items: [
    {id: 19993, name: "item 1"},
    {id: 70264, name: "item 2"},
    {id: 99737, name: "item 3"},
    {id: 65474, name: "item 4"},
    {id: 76765, name: "item 5"},
    {id: 07078, name: "item 6"}
]

I'm trying to create a new array of items for each category, based on the ID's included in the categories.items array.

So for category 1 the output should be:

[
    {id: 19993, name: "item 1"},
    {id: 99737, name: "item 3"}
]

I know I can do this with a mess of loops, pushing into an array but was wondering if there was an shorter ES6 way of achieving this?

Thanks

2
  • 1
    You're asking for the "best way" which will generate primarily opinion-based answers (which is why there are already three different answers...) - which is off-topic for SO Commented Mar 9, 2019 at 11:01
  • By the way, "shorter" is not "better". Looking for the shortest possible code is a naive approach of programming. Think of performances. Commented Mar 9, 2019 at 13:29

4 Answers 4

2

Create a Map by item id out of the items array. Use Array.map() to iterate the categories array. For each category, create a new object using object spread, and populate the items array from the Map:

const categories = [{"id":1,"name":"category 1","items":[19993,99737]},{"id":2,"name":"category 2","items":[70264,65474,7078]},{"id":3,"name":"category 3","items":[76765]}]

const items = [{"id":19993,"name":"item 1"},{"id":70264,"name":"item 2"},{"id":99737,"name":"item 3"},{"id":65474,"name":"item 4"},{"id":76765,"name":"item 5"},{"id":7078,"name":"item 6"}]

const itemsMap = new Map(items.map(o => [o.id, o]))

const result = categories.map(o => ({
  ...o,
  items: o.items.map(id => itemsMap.get(id))
}))

console.log(result)

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

Comments

2

You can do it succinctly using Array.prototype.map(), Array.prototype.find() and Array.prototype.filter():

const categories = [
    {id: 1,name: "category 1",items: [19993, 99737]},
    {id: 2,name: "category 2",items: [70264, 65474, 07078]},
    {id: 3,name: "category 3",items: [76765]}
];

const items = [
    {id: 19993, name: "item 1"},
    {id: 70264, name: "item 2"},
    {id: 99737, name: "item 3"},
    {id: 65474, name: "item 4"},
    {id: 76765, name: "item 5"},
    {id: 07078, name: "item 6"}
];

const result = categories.map(c => ({
    ...c,
    items: c.items.map(id => items.find(i => id === i.id)).filter(Boolean)
}));

console.log(result);

1 Comment

@leaf, awesome! :)
1

You could find the category and the items.

function getItemsByCategory(id) {
    var category = categories.find(o => o.id === id);
    if (category) {
        return category.items.map(id => items.find(o => o.id === id));
    }
}

var categories = [{ id: 1, name: "category 1", items: [19993, 99737] }, { id: 2, name: "category 2", items: [70264, 65474, 07078] }, { id: 3, name: "category 3", items: [76765] }],
    items = [{ id: 19993, name: "item 1" }, { id: 70264, name: "item 2" }, { id: 99737, name: "item 3" }, { id: 65474, name: "item 4" }, { id: 76765, name: "item 5" }, { id: 07078, name: "item 6" }];

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

Comments

1

You can use reduce, forEach and find

Here idea is

  • First for each item array in categories we find the matching element in items variable.
  • If we find a matching element we add it to op else return op without any change

let categories = [{id: 1,name: "category 1",items: [19993, 99737]},{id: 2,name: "category 2",items: [70264, 65474, 07078]},{id: 3,name: "category 3",items: [76765]}]
let items = [{id: 19993, name: "item 1"},{id: 70264, name: "item 2"},{id: 99737, name: "item 3"},   {id: 65474, name: "item 4"},{id: 76765, name: "item 5"},{id: 07078, name: "item 6"},]

let op = categories.reduce((op, {name, items:cartItems}) => {
  cartItems.forEach(key => {
    let value = items.find(({id}) => id === key)
    if(value){
      op[name] = op[name] || []
      op[name].push(value)
    }
  })
  return op
},{})

console.log(op)

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.