Home > OS >  Merge/replace objects from different arrays if they have common property value (javascript)
Merge/replace objects from different arrays if they have common property value (javascript)

Time:08-31

I have a problem merging two objects. I work with Contentful API, and the structure of provided data for links comes not in one object so it could be easily processed further, but in separate array of objects. The connection between them is the id. The goal is to merge those objects or maybe even replace existing one.

Here is the data structure:

const dataDictionary = {
  includes: {
    entry: [
      {
       fields: {data: 'https://link1.com'},
       sys: {id: 12345}
      },
      {
       fields: {data: 'https://link2.com'},
       sys: {id: 16349}
      },
      {
        fields: {data: 'https://link3.com'},
        sys: {id: 14345}
      },
      {
        fields: {data: 'https://link4.com'},
        sys: {id: 98765}
      },
      {
        fields: {data: 'https://link5.com'},
        sys: {id: 43210}
      },
    ]
  },
  items: [
    {
      fields: {
        urls: [
          {
            id: 14345,
            type: 'link'
          },
          {
            id: 16349,
            type: 'link'
          }
        ],
        dataKey: 'dataPrpoperty',
        dataKey2: 'dataPrpoperty2',
      }
    },
    {
      fields: {
        urls: [
          {
            id: 12345,
            type: 'link'
          },
        ],
        dataKey: 'dataPrpoperty',
        dataKey2: 'dataPrpoperty2',
        helpfulLinks: [
          {
            id: 98765,
            type: 'link'
          },
          {
            id: 43210,
            type: 'link'
          }
        ]
      }
    },
  ]
}

What I want to achieve is to have all arrays of objects with links inside items, been merged and mutated with actual links value from includes.

My code:

const mergeByValue = (arrayTo, arrayFrom) => {
    const finalMerge = arrayTo.map(itm => ({
      ...arrayFrom.find((item) => (item.sys.id === itm.id) && item),
      ...itm
    }));
    return finalMerge;
}

const parseDataDictionary = (dataDictionary) => {
  const pages = dataDictionary.items;
  const includes = dataDictionary.includes.Entry;
  pages.map(page => {
   return Object.entries(page.fields).map(([key, value]) => {
     if (Object.prototype.toString.call(value) === '[object Array]') {
      return mergeByValue(value, includes);
     }
   })
  })
}

parseDataDictionary(pageDictionaryData);

Seems like Everything works, I mean merging, but in the end it is not returning the merged value. If that could be possible, would be grateful for any clue. Thanks.

UPD: The expected result:

{
 items: [
    {
      fields: {
        urls: [
          {
            id: 14345,
            type: 'link',
            data: 'https://link3.com'
          },
          {
            id: 16349,
            type: 'link',
            data: 'https://link2.com'
          }
        ],
        dataKey: 'dataPrpoperty',
        dataKey2: 'dataPrpoperty2',
      }
    },
    {
      fields: {
        urls: [
          {
            id: 12345,
            type: 'link'
            data: 'https://link1.com'
          },
        ],
        dataKey: 'dataPrpoperty',
        dataKey2: 'dataPrpoperty2',
        helpfulLinks: [
          {
            id: 98765,
            type: 'link'
            data: 'https://link4.com'
          },
          {
            id: 43210,
            type: 'link'
            data: 'https://link5.com'
          }
        ]
      }
    },
  ]
}

CodePudding user response:

map return new array so if I am not wrong, you need to assign the result of your mapping and return that.


              let newValues = pages.map((page) => {
                return Object.entries(page.fields).map(([key, value]) => {
                    if (
                        Object.prototype.toString.call(value) ===
                        "[object Array]"
                    ) {
                        return mergeByValue(value, includes);
                    }
                });
            });
            return newValues;

CodePudding user response:

Another one approach:

const dataDictionary = {includes: {entry: [{fields: {data: 'https://link1.com'},sys: {id: 12345}},{fields: {data: 'https://link2.com'},sys: {id: 16349}},{fields: {data: 'https://link3.com'},sys: {id: 14345}},{fields: {data: 'https://link4.com'},sys: {id: 98765}},{fields: {data: 'https://link5.com'},sys: {id: 43210}},]},items: [{fields: {urls: [{id: 14345,type: 'link'},{id: 16349,type: 'link'}],dataKey: 'dataPrpoperty',dataKey2: 'dataPrpoperty2',}},{fields: {urls: [{id: 12345,type: 'link'},],dataKey: 'dataPrpoperty',dataKey2: 'dataPrpoperty2',helpfulLinks: [{id: 98765,type: 'link'},{id: 43210,type: 'link'}]}},]}
          
const entryLinks = dataDictionary.includes.entry
  .reduce((acc, {sys: {id}, fields: {data} }) => ({ ...acc, [id]: data }), {});
 
const addLinks = (ids) => ids.map((e) => ({ ...e, data: entryLinks[e.id] }));
  
const items = dataDictionary.items.map(
  ({ fields }) => Object.values(fields).map(
    (value) => Array.isArray(value) ? addLinks(value) : value
  )
);
         
console.log(items);
.as-console-wrapper { max-height: 100% !important; top: 0 }

  • Related