javascript - Better way to join two arrays of objects on two properties? -


i'm trying combine 2 arrays of objects, based on 2 properties, , rewrite names of other properties in joined dataset.

this datasets like:

var xdata = [     { row_id: 1, date: '2013-04-01', cost: 18 },    { row_id: 2, date: '2013-04-01', cost: 27 } ... ]; var ydata = [     { row_id: 1, date: '2013-04-01', cost: 48 },    { row_id: 3, date: '2013-04-01', cost: 37 } ... ]; 

the properties want join on row_id , date properties, , want rewrite cost x_cost , y_cost respectively. want deal missing values. want end with:

var combineddata = [     { row_id: 1, date: '2013-04-01', x_cost: 18, y_cost: 48 },    { row_id: 2, date: '2013-04-01', x_cost: 27, y_cost: null },    { row_id: 3, date: '2013-04-01', x_cost: null, y_cost: 37 } ... ]; 

this code right now. it's pretty horrible:

combinexandydatasets: function(xdata, ydata) {     // index both datasets id , date.      var x_indexed_by_id_and_date = {};     xdata.foreach(function(d) {         var k = d.row_id + '_' + d.date;         x_indexed_by_id_and_date[k] = d;     });     var y_indexed_by_id_and_date = {};     ydata.foreach(function(d) {         var k = d.row_id + '_' + d.date;         y_indexed_by_id_and_date[k] = d;     });      var combineddata = [];     // iterate on ydata, join xdata if possible.     (var row_id in y_indexed_by_id_and_date) {         var row = json.parse(json.stringify(y_indexed_by_id_and_date[row_id]));         row.y_cost = +y_indexed_by_id_and_date[row_id].cost;         if (row_id in x_indexed_by_id_and_date) {             row.x_cost = +x_indexed_by_id_and_date[row_id].cost;         } else {             row.x_cost = null;         }         combineddata.push(row);     }     // iterate on xdata, add wasn't in ydata.     (var x_row_id in x_indexed_by_id_and_date) {         if (!(x_row_id in y_indexed_by_id_and_date)) {             var x_row = json.parse(json.stringify(x_indexed_by_id_and_date[x_row_id]));             x_row.y = null;             x_row.x = +x_row.cost;             combineddata.push(x_row);         }     }     return combineddata; } 

what can make less awful?

i'm using jquery, , add e.g. underscore if help.

you take advantage of reduce reduce each array dictionary , convert dictionary array. (vanilla js, not ie 8 compatible out-of-the-box):

var xdata = [      { row_id: 1, date: '2013-04-01', cost: 18 },     { row_id: 2, date: '2013-04-01', cost: 27 }  ];  var ydata = [      { row_id: 1, date: '2013-04-01', cost: 48 },     { row_id: 3, date: '2013-04-01', cost: 37 }  ];    var xdatadict = xdata.reduce(function(p,c) {      createdictionaryentry(p,c,c.cost,null)      return p;  },{});    xandydatadict = ydata.reduce(function(p,c) {      createdictionaryentry(p,c,null,c.cost)      return p;  }, xdatadict);      var combineddata = object.keys(xandydatadict).map(function(key) {       return xandydatadict[key];   });    alert(json.stringify(combineddata));      function createdictionaryentry(p,c,x_cost,y_cost) {      var key = c.row_id + "-" + c.date;      if (p[key]) {          p[key].x_cost = p[key].x_cost || x_cost;          p[key].y_cost = p[key].y_cost || y_cost;      } else {          p[key] = {              row_id: c.row_id,              date: c.date,              x_cost: x_cost,              y_cost: y_cost          }      }  }

note combineddata won't in guaranteed order, if that's important, can sort afterwards.

using underscore:

var xdata = [      { row_id: 1, date: '2013-04-01', cost: 18 },     { row_id: 2, date: '2013-04-01', cost: 27 }  ];  var ydata = [      { row_id: 1, date: '2013-04-01', cost: 48 },     { row_id: 3, date: '2013-04-01', cost: 37 }  ];    var xdatadict = _.reduce(xdata, function(p,c) {      createdictionaryentry(p,c,c.cost,null)      return p;  },{});    xandydatadict = _.reduce(ydata,function(p,c) {      createdictionaryentry(p,c,null,c.cost)      return p;  }, xdatadict);      var combineddata = _.map(object.keys(xandydatadict),function(key) {       return xandydatadict[key];   });    alert(json.stringify(combineddata));      function createdictionaryentry(p,c,x_cost,y_cost) {      var key = c.row_id + "-" + c.date;      if (p[key]) {          p[key].x_cost = p[key].x_cost || x_cost;          p[key].y_cost = p[key].y_cost || y_cost;      } else {          p[key] = {              row_id: c.row_id,              date: c.date,              x_cost: x_cost,              y_cost: y_cost          }      }  }
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>


Comments