0

I have 2 arrays of 20 objects that I want to merge by name. The order of the names in each array is different, and the order is important and has to be left as is. This prevents me from a traditional sort and for loop approach. Basically, what I have is:

var tempList1 = [
   {'manager':'John', 'x1':0, 'y1':0, 'x2':1, 'y2':1},
   {'manager':'Tom', 'x1':0, 'y1':50, 'x2':1, 'y2':1},
   {'manager':'Julie', 'x1':0, 'y1':80, 'x2':1, 'y2':1},
...
];

var tempList2 = [
   {'manager':'Tom', 'x3':0, 'y3':10, 'x4':1, 'y4':1},
   {'manager':'Julie', 'x3':0, 'y3':90, 'x4':1, 'y4':1},
   {'manager':'John', 'x3':0, 'y3':50, 'x4':1, 'y4':1},
...
];

Notice that John is at index 0 in tempList1 but is at index 2 at tempList2. When I tried:

          for (var k = 0; k < managerList.length; k++) {
            let merged = {...tempList1[k],...tempList2[k]}
            combinedList.push(merged);
          }

I was making the mistake of assuming the order was the same in each array -- when its not.

End result should be:

var combinedList = [
    {'manager':'John', 'x1':0, 'y1':0, 'x2':1, 'y2':1, 'x3':0, 'y3':50, 'x4':1, 'y4':1},
    {'manager':'Tom', 'x1':0, 'y1':50, 'x2':1, 'y2':1, 'x3':0, 'y3':10, 'x4':1, 'y4':1},
    {'manager':'Julie', 'x1':0, 'y1':80, 'x2':1, 'y2':1, 'x3':0, 'y3':90, 'x4':1, 'y4':1}
];

Question

How can I merge objects so that only objects when the same manager value are merged with each other in my array?

Arash Howaida
  • 2,575
  • 2
  • 19
  • 50

2 Answers2

2

From one of the lists, create an object indexed by manager. Then, when iterating over the other list, just lookup the same manager property and merge:

var tempList1 = [
   {'manager':'John', 'x1':0, 'y1':0, 'x2':1, 'y2':1},
   {'manager':'Tom', 'x1':0, 'y1':50, 'x2':1, 'y2':1},
   {'manager':'Julie', 'x1':0, 'y1':80, 'x2':1, 'y2':1}
];

var tempList2 = [
   {'manager':'Tom', 'x3':0, 'y3':10, 'x4':1, 'y4':1},
   {'manager':'Julie', 'x3':0, 'y3':90, 'x4':1, 'y4':1},
   {'manager':'John', 'x3':0, 'y3':50, 'x4':1, 'y4':1}
];

const list1ByManager = tempList1.reduce((a, item) => {
  a[item.manager] = item;
  return a;
}, {});

const combined = tempList2.map((item2) => ({
  ...list1ByManager[item2.manager],
  ...item2
}));

console.log(combined);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • I'm not sure why, but all the `y1` and `y2` values all ended up the same value -- the value belonging to the last manager. Is that significant somehow? Before your code all the `y1`s and `y2`s were preserved. I wonder what makes them truncate to the last value? – Arash Howaida Aug 08 '19 at 03:40
  • In the input, the `x1` and `y1` properties for the 1st and 3rd object of `tempList1` are the same (0), so they're the same in the output as well. (The `Tom` object in `tempList1` is identical to the `Tom` object in `tempList2`, and does not have an `x1` or `y1` property) – CertainPerformance Aug 08 '19 at 03:43
  • Sorry, I meant for Tom to have an `x1` and `y1`. I updated my sample code to be more accurate of my actual data. – Arash Howaida Aug 08 '19 at 03:47
  • Looks to work as desired. The different `y1` properties in `tempList1` all get copied over to the appropriate other object in the `combined` array. – CertainPerformance Aug 08 '19 at 03:48
  • You are probably right, but the error persists. I have updated https://stackoverflow.com/questions/57386189/d3-append-many-short-paths this post with my full data if you are curious. I concede the code is a little long... – Arash Howaida Aug 08 '19 at 04:04
1

As you need to have one case per management, I transformed your array to an object with the manager's name as the key and then transformed to an array of objects again

var tempList1 = [
  {'manager':'John', 'x1':0, 'y1':0, 'x2':1, 'y2':1},
  {'manager':'Tom', 'x3':0, 'y3':0, 'x4':1, 'y4':1},
  {'manager':'Julie', 'x1':0, 'y1':0, 'x2':1, 'y2':1},
].reduce(function(result, obj) {
  result[obj.manager] = obj
  return result
}, {});

console.log(tempList1)

var tempList2 = [
  {'manager':'Tom', 'x3':0, 'y3':0, 'x4':1, 'y4':1},
  {'manager':'Julie', 'x3':0, 'y3':0, 'x4':1, 'y4':1},
  {'manager':'John', 'x3':0, 'y3':0, 'x4':1, 'y4':1},
].reduce(function(result, obj) {
  result[obj.manager] = obj
  return result
}, {});

var temp = []

for (var key in tempList1) {
  temp.push({ ...tempList1[key], ...tempList2[key] })
}

console.log(temp)
leocabrallce
  • 163
  • 1
  • 8