devjson
devjson

Reputation: 123

How to merge JavaScript object array using reduce?

There's so many of post here regarding merging javaScript array objects relative to my question most of them are merging 2 arrays in my case it's different.

I have JSON from API I mapped and filtered them because i only need the 'tags'

Here's my code:

JSON.map((key) => (key.tags))
.filter(function (element) {
    return element !== undefined;
})

Here's my result:

   [ 
      { 
    "web_devt": { 
      "item_id": "858850847", 
      "tag": "web_devt" 
    } 
  }, 
  { 
    "web_devt": { 
      "item_id": "1004644524", 
      "tag": "web_devt" 
    } 
  }, 
  { 
    "pdo": { 
      "item_id": "1056300113", 
      "tag": "pdo" 
    }, 
    "php": { 
      "item_id": "1056300113", 
      "tag": "php" 
    }, 
    "web_devt": { 
      "item_id": "1056300113", 
      "tag": "web_devt" 
    } 
  }, 
  { 
    "parallax scrolling": { 
      "item_id": "1087678088", 
      "tag": "parallax scrolling" 
    } 
  }, 
  { 
    "react": { 
      "item_id": "2435593852", 
      "tag": "react" 
    } 
  }, 
  { 
    "javascript": { 
      "item_id": "2435595088", 
      "tag": "javascript" 
    } 
  }, 
  { 
    "react": { 
      "item_id": "2465629468", 
      "tag": "react" 
    } 
  } 
] 

I want to merge them like this:

[
{
"web_devt": [
    item_id: "765558416", 
        item_id: "765558416",
        item_id: "765558416",
        ...]
},
 {
"react": [
    item_id: "765558416",
    item_id: "765558416",
    item_id: "765558416",
    ...]
},
{
"JavaScipt": [
    item_id: "765558416",
    item_id: "765558416",
    item_id: "765558416",
    ...]
}

]

and so on ... Basically all the same tags will merge How you do this in reduce or any solution but not loadash or any third party?

Upvotes: 3

Views: 8369

Answers (3)

Shidersz
Shidersz

Reputation: 17190

Here is my try using Array.reduce() with a nested Object.values() and Array.forEach():

const input = [ 
  { 
    "web_devt": {"item_id": "858850847", "tag": "web_devt"} 
  }, 
  { 
    "web_devt": {"item_id": "1004644524", "tag": "web_devt"} 
  }, 
  { 
    "pdo": {"item_id": "1056300113", "tag": "pdo"}, 
    "php": {"item_id": "1056300113", "tag": "php"}, 
    "web_devt": {"item_id": "1056300113", "tag": "web_devt"} 
  }, 
  { 
    "parallax scrolling": {"item_id": "1087678088", "tag": "parallax scrolling"} 
  }, 
  { 
    "react": { "item_id": "2435593852", "tag": "react"} 
  }, 
  { 
    "javascript": {"item_id": "2435595088", "tag": "javascript"} 
  }, 
  { 
    "react": {"item_id": "2465629468", "tag": "react"} 
  } 
];

let res = input.reduce((acc, obj) =>
{
    Object.values(obj).forEach(({item_id, tag}) =>
    {
        acc[tag] = acc[tag] || {[tag]:[]}
        acc[tag][tag].push(item_id);
    });
    return acc;
}, {});

console.log(Object.values(res));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper{max-height:100% !important; top:0}

Upvotes: 1

Shubham Khatri
Shubham Khatri

Reputation: 281696

Your desired output syntax is invalid. You cannot have an array with keys nor you can have an object with multiple keys of the same name.

However if you want have an array of ids, you could use reduce and group the data and for the individual item use Object.entries to get the key and the value within the object.

var data = [ 
  { 
    "web_devt": { 
      "item_id": "858850847", 
      "tag": "web_devt" 
  } 
  }, 
  { 
    "web_devt": { 
      "item_id": "1004644524", 
      "tag": "web_devt" 
    } 
  }, 
  { 
    "pdo": { 
      "item_id": "1056300113", 
      "tag": "pdo" 
    }, 
    "php": { 
      "item_id": "1056300113", 
      "tag": "php" 
    }, 
    "web_devt": { 
      "item_id": "1056300113", 
      "tag": "web_devt" 
    } 
  }, 
  { 
    "parallax scrolling": { 
      "item_id": "1087678088", 
      "tag": "parallax scrolling" 
    } 
  }, 
  { 
    "react": { 
      "item_id": "2435593852", 
      "tag": "react" 
    } 
  }, 
  { 
    "javascript": { 
      "item_id": "2435595088", 
      "tag": "javascript" 
    } 
  }, 
  { 
    "react": { 
      "item_id": "2465629468", 
      "tag": "react" 
    } 
  } 
] 

const res = data.reduce((acc, item) => {
  Object.entries(item).forEach((attr) => {
    const [key,value] = attr;
    if(value.tag !== undefined) {
      if (acc[key]){
        acc[key].push(value.item_id);
      }
      else {
        acc[key] = [value.item_id];
      }
    }
  });
  
  return acc;
}, {})
console.log(res);

Upvotes: 2

CertainPerformance
CertainPerformance

Reputation: 370769

Assuming that the inner arrays are meant to contain objects, use .reduce to group the input objects into an object indexed by item_id, then transform that object into an array using Object.entries:

const input = [ { 
    "web_devt": { 
      "item_id": "858850847",
      "tag": "web_devt" 
    } 
  },  
  { 
    "web_devt": { 
      "item_id": "1004644524",
      "tag": "web_devt" 
    } 
  },  
  { 
    "pdo": { 
      "item_id": "1056300113",
      "tag": "pdo" 
    },
     
    "php": { 
      "item_id": "1056300113",
      "tag": "php" 
    },
     
    "web_devt": { 
      "item_id": "1056300113",
      "tag": "web_devt" 
    } 
  },  
  { 
    "parallax scrolling": { 
      "item_id": "1087678088",
      "tag": "parallax scrolling" 
    } 
  },  
  { 
    "react": { 
      "item_id": "2435593852",
      "tag": "react" 
    } 
  },  
  { 
    "javascript": { 
      "item_id": "2435595088",
      "tag": "javascript" 
    } 
  },  
  { 
    "react": { 
      "item_id": "2465629468",
      "tag": "react" 
    } 
  } 
];
const outputObj = input.reduce((a, outerObj) => {
  Object.entries(outerObj).forEach(([key, { item_id }]) => {
    if (!a[key]) a[key] = [];
    a[key].push({ item_id });
  });
  return a;
}, {});
const output = Object.entries(outputObj).map(([key, arr]) => ({ [key]: arr }));
console.log(output);

Upvotes: 1

Related Questions