You could split the name by minus sign and use the first part as role_name and the second part as report_name property of the inner object.
var data = [{ name: "client_management-testmonitoring", value: 0 }, { name: "client_operations-testmonitoring", value: 0 }, { name: "tpl_management-testmonitoring", value: 0 }, { name: "tpl_operations-testmonitoring", value: 0 }, { name: "channel_partner-testmonitoring", value: 0 }, { name: "operator-testmonitoring", value: 0 }, { name: "financier-testmonitoring", value: 0 }, { name: "client_management-test_monitoring_2", value: 0 }, { name: "client_operations-test_monitoring_2", value: 0 }, { name: "tpl_management-test_monitoring_2", value: 0 }, { name: "tpl_operations-test_monitoring_2", value: 0 }, { name: "channel_partner-test_monitoring_2", value: 0 }, { name: "operator-test_monitoring_2", value: 0 }, { name: "financier-test_monitoring_2", value: 0 }, { name: "client_management-test_monitoring_3", value: 0 }, { name: "client_operations-test_monitoring_3", value: 0 }, { name: "tpl_management-test_monitoring_3", value: 0 }, { name: "tpl_operations-test_monitoring_3", value: 0 }, { name: "channel_partner-test_monitoring_3", value: 0 }, { name: "operator-test_monitoring_3", value: 0 }, { name: "financier-test_monitoring_3", value: 0 }], result = data.reduce(function (hash) { return function (r, a) { var parts = a.name.split('-'); if (!hash[parts[0]]) { hash[parts[0]] = {}; rr[0].role.push({ role: [{ role_name: parts[0], report_name: [hash[parts[0]]] }] }); } if (!parts[1].match(/\d$/)) { parts[1] = 'test_monitoring_1'; } hash[parts[0]][parts[1]] = a.value; return r; } }(Object.create(null)), [{ report_name: "monitoring", role: [] }]); console.log(result); .as-console-wrapper { max-height: 100% !important; top: 0; }