简体   繁体   中英

combine array of objects by key

I am trying to combine/merge 2 array of objects by key in my case id.

Objective:

  1. I am expecting a results where I would have array containing all objects with ids 1,2,3,4 as per example
  2. Order of merging should not affect number of objects in result for example combine(arr1,arr2) or combine(arr2,arr1) should have array with same number of objects
  3. Order of merging can only affect resulting object for example in case of combine(arr1,arr2) arr2 key,values pair can override arr1 key,values just like deep jquery extend $.extend( true, arr1ObJ,arr2ObJ );

JSFIDDLE: https://jsfiddle.net/bababalcksheep/u2c05nyj/

Sample Data:

var arr1 = [{
  id: 1,
  name: "fred",
  title: "boss"
}, {
  id: 2,
  name: "jim",
  title: "nobody"
}, {
  id: 3,
  name: "bob",
  title: "dancer"
}];
var arr2 = [{
  id: 1,
  wage: "300",
  rate: "day"
}, {
  id: 2,
  wage: "10",
  rate: "hour"
}, {
  id: 4,
  wage: "500",
  rate: "week"
}];
var Result = [{
  "id": 1,
  "name": "fred",
  "title": "boss",
  "wage": "300",
  "rate": "day"
}, {
  "id": 2,
  "name": "jim",
  "title": "nobody",
  "wage": "10",
  "rate": "hour"
}, {
  id: 3,
  name: "bob",
  title: "dancer" 
}, {
  id: 4,
  wage: "500",
  rate: "week"
}];

Here's a solution. It basically goes through each element of arr2 and checks to see if there's an element with a matching ID arr1. If so, it updates the matching element in arr1 with arr2's values. If there is no match, it simply pushes the element in arr2 onto arr1.

var arr1 = [{id: 1,name: 'fred',title: 'boss'}, 
            {id: 2,name: 'jim',title: 'nobody'}, 
            {id: 3,name: 'bob',title: 'dancer'}];

var arr2 = [{id: 1,wage: '300',rate: 'day'}, 
            {id: 2,wage: '10',rate:'hour'},
            {id: 4,wage: '500',rate: 'week'}];

function combineArrays(arr1, arr2) {
  for(var i = 0; i < arr2.length; i++) {
    // check if current object exists in arr1
    var idIndex = hasID(arr2[i]['id'], arr1);
    if(idIndex >= 0){
      //update
      for(var key in arr2[i]){
        arr1[idIndex][key] = arr2[i][key];
      }
    } else {
      //insert
      arr1.push(arr2[i]);
    }
  }

  return arr1;
}

//Returns position in array that ID exists
function hasID(id, arr) {
  for(var i = 0; i < arr.length; i ++) {
    if(arr[i]['id'] === id)
    {
      return i;
    }
  }

  return -1;
}

var combine = combineArrays(arr1, arr2);
output(combine);

/* pretty Print */
function output(inp) {
  var str = JSON.stringify(inp, undefined, 4);
  $('body').append($('<pre/>').html(str));
}

 var arr1 = [{ id: 1, name: 'fred', title: 'boss' }, { id: 2, name: 'jim', title: 'nobody' }, { id: 3, name: 'bob', title: 'dancer' }]; var arr2 = [{ id: 1, wage: '300', rate: 'day' }, { id: 2, wage: '10', rate: 'hour' }, { id: 4, wage: '500', rate: 'week' }]; function combineArrays(arr1, arr2) { for (var i = 0; i < arr2.length; i++) { var idIndex = hasID(arr2[i]['id'], arr1); if (idIndex >= 0) { for (var key in arr2[i]) { arr1[idIndex][key] = arr2[i][key]; } } else { arr1.push(arr2[i]); } } return arr1; } function hasID(id, arr) { for (var i = 0; i < arr.length; i++) { if (arr[i]['id'] === id) { return i; } } return -1; } var combine = combineArrays(arr1, arr2); output(combine); /* pretty Print */ function output(inp) { var str = JSON.stringify(inp, undefined, 4); $('body').append($('<pre/>').html(str)); } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

How about something along the lines of this:

function combineArrays(arr1, arr2, keyFunc) {
    var combined = [],
        keys1 = arr1.map(keyFunc),
        keys2 = arr2.map(keyFunc),
        pos1 = keys1.map(function (id) {
            return keys2.indexOf(id);
        }),
        pos2 = keys2.map(function (id) {
            return keys1.indexOf(id);
        });

    arr1.forEach(function (item, i) {
        combined.push( $.extend(item, arr2[pos1[i]]) );
    });
    arr2.forEach(function (item, i) {
        if (pos2[i] === -1) combined.push( item );
    });
    return combined;    
}

used as

var combine = combineArrays(arr1, arr2, function (item) {
    return item.id;
});

 var arr1 = [ { id: 1, name: 'fred', title: 'boss' }, { id: 2, name: 'jim', title: 'nobody' }, { id: 3, name: 'bob', title: 'dancer' } ]; var arr2 = [ { id: 1, wage: '300', rate: 'day' }, { id: 2, wage: '10', rate: 'hour' }, { id: 4, wage: '500', rate: 'week' } ]; function combineArrays(arr1, arr2, keyFunc) { var combined = [], keys1 = arr1.map(keyFunc), keys2 = arr2.map(keyFunc), pos1 = keys1.map(function (id) { return keys2.indexOf(id); }), pos2 = keys2.map(function (id) { return keys1.indexOf(id); }); arr1.forEach(function (item, i) { combined.push( $.extend(item, arr2[pos1[i]]) ); }); arr2.forEach(function (item, i) { if (pos2[i] === -1) combined.push( item ); }); return combined; } var combine = combineArrays(arr1, arr2, function (item) { return item.id; }); output(combine); // // // /* pretty Print */ function output(inp) { var str = JSON.stringify(inp, undefined, 4); $('body').append($('<pre/>').html(str)); } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM