1

I currently have 2 different arrays of objects

const arr1 = [
{
  groupId: "Category",
  options: [
     {name: "cookies", id: 1111},
     {name: "tv", id: 2222}
  ]
},
{
  groupId: "Brand",
  options: [
     {name: "test1", id: 2222}
  ]
},
{
  groupId: "Price",
  options: [
     {name: "test2", id: 4444}
  ]
}
]
const arr2 = [
  {
    id: 1111,
    url: "/test"
  },
  {
    id: 2222,
    url: "/test1"
  },
  {
    id: 3333,
    url: "/test2
  }
]

How would I merge arr2's object into arr1's object based on the matching obj ids? So for example the expected should be

const result = [
  {
  groupId: "Category",
  options: [
     {name: "cookies", id: 1111, url: "/test"},
     {name: "tv", id: 2222, url: "/test1"}
  ]
},
{
  groupId: "Brand",
  options: [
     {name: "test1", id: 2222, url: "/test1"}
  ]
},
{
  groupId: "Price",
  options: [
     {name: "test2", id: 4444}
  ]
}
]

This is what I currently have but I can't seem to get it to give me the expected result.

const getNewArr = (arr2, arr1) => {
    const categoryGroup = arr1.find(group => group.groupId === "Category");
    if (categoryGroup) {
      let matchGroup;
      categoryGroup.options.map(group => {
        matchGroup = arr2.filter(child =>
          child.categoryId === group.id ? {...group, child} : group
        );
      });
      return {...categoryGroup.options,...matchGroup};
    }
    return arr1;
  }

I tried a few things but I am unable to get it working so far. Am I missing something or is there something else that needs to be done?

2 Answers 2

2

Here's an option using nested .map() calls to iterate over each options array and a .find() call to look for relevant entries in arr2 by id.

const
  arr1 = [{ groupId: "Category", options: [{ name: "cookies", id: 1111 }, { name: "tv", id: 2222 }] }, { groupId: "Brand", options: [{ name: "random", id: 3333 }] }, { groupId: "Price", options: [{ name: "random2", id: 4444 }] }],
  arr2 = [{ id: 1111, url: "/test", other: 'other-prop' }, { id: 2222, url: "/test1" }, { id: 3333, url: "/test2" }],

  mergeById = (arr1, arr2) =>
    arr1.map(({ options, ...rest }) => (
      {
        ...rest,
        options: options.map(option => (
          {
            ...option,
            ...arr2.find(_option => _option.id === option.id)
          }
        ))
      }
    ));

const merged = mergeById(arr1, arr2);

console.log(JSON.stringify(merged, null, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }

If the second array can contain multiple elements for a given id you can use Object.assign() and spread the result of a .filter() call to merge all the relevant objects.

const
  arr1 = [{ groupId: "Category", options: [{ name: "cookies", id: 1111 }, { name: "tv", id: 2222 }] }, { groupId: "Brand", options: [{ name: "random", id: 3333 }] }, { groupId: "Price", options: [{ name: "random2", id: 4444 }] }],
  arr2 = [{ id: 1111, url: "/test" }, { id: 2222, url: "/test1" }, { id: 1111, other: 'other-prop' }, { id: 3333, url: "/test2" }],

  mergeById = (arr1, arr2) =>
    arr1.map(({ options, ...rest }) => (
      {
        ...rest,
        options: options.map(option => (
          Object.assign(option, ...arr2.filter(_option => _option.id === option.id))
        ))
      }
    ));

const merged = mergeById(arr1, arr2);

console.log(JSON.stringify(merged, null, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

1 Comment

Thank you for the help! I spent probably too many hours trying to get it to work. I can also put this to use next time I run into the same thing again! Gained some knowledge!
0

First of all, as I see arr 2 url should be "/test2" and in your result array, it is missing url for id: 3333.

The main idea is just to spread all the properties existing on arr1 and add properties on the arr2 with the same id, In the example below, first of all, I have converted arr2 into an object with id key, so later, you shouldn't use find method to access element.

// const arr2 = [{ id: 1111, url: "/test"}, { id: 2222, url: "/test1"}];
// will be transformed to{"1111": {url: "/test"}, "2222": {url: "/test1"}} after line below
const obj2 = Object.fromEntries(arr2.map(({id, ...el}) => [id, el]));

const arr3 = arr1.map((el) => ({
  ...el,
  options: el.options.map((oEl) => ({
    ...oEl,
    ...obj2[oEl.id],
  })),
}));

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.