0

I'd like to merge 2 arrays of objects in Javascript, the source array is something like:

padding = [{'t': 1, 'c': 0}, {'t': 2, 'c': 0}, {'t': 3, 'c': 0}]
data = [{'t': 3, 'c': 5}]

The result should look like:

result = [{'t': 1, 'c': 0}, {'t': 2, 'c': 0}, {'t': 3, 'c': 3}]

Please note that data is being populated into padding by matching 't'. I've tried various method, such as jQuery $.extend({}, padding, data), however it doesn't output correctly.

Appreciate if you share something. Thanks.

Edit 1 (10 April 2020)

As @codemaniac pointed out, I had a typo, the result should be:

result = [{'t': 1, 'c': 0}, {'t': 2, 'c': 0}, {'t': 3, 'c': 5}]

Additional (10 April 2020)

I have padding length of 1000, for data, it should be the subset of padding by the key 't'.

I am looking for efficient way of "merging" and "replacing" the data into padding, some call it "addition", given that padding will always padded with 'c': 0 for every object.

I don't mind to try out lodash JS utility if it's possible.

6
  • 7
    how come it become {'t': 3, 'c': 3} ? Commented Apr 9, 2020 at 16:27
  • How did you achieve the final result? Please example the problem properly :) Commented Apr 9, 2020 at 17:05
  • @CodeManiac I've corrected as you mentioned. Commented Apr 10, 2020 at 6:28
  • @YousufKhan I've made a typo in the original post, I have added an edit to the post. Commented Apr 10, 2020 at 6:31
  • ok and what will be the final result if data = [{'t': 4, 'c': 5}] and padding = [{'t': 1, 'c': 0}, {'t': 2, 'c': 0}, {'t': 3, 'c': 0}]? Commented Apr 10, 2020 at 6:39

4 Answers 4

1

I assume you want an addition, to get the proper size of your element (padding + width)

const padding = [{
  t: 1,
  c: 0,
}, {
  t: 2,
  c: 0,
}, {
  t: 3,
  c: 0,
}];

const data = [{
  t: 3,
  c: 5,
}];

// Use a reduce to build the new array
function mergeData(d1, d2) {
  return d2.reduce((tmp, x) => {
    // Check if the array already contains the key 't'
    const found = tmp.find(y => y.t === x.t);

    // If it does, add 'c' together
    if (found) {
      found.c += x.c;
    } else {
      // else, add the missing entry
      tmp.push(x);
    }

    return tmp;
  }, d1);
}

console.log(mergeData(data, padding));

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. The result seems to be not sorted. The purpose of this question being that I want to align some randomly missing data points in “data” with “padding” by key “t” so that they appear uniform on a chart.
I use mergeData(padding, data) instead. I got it working by switching the parameters in mergeData method. Hence, accepted answer :)
1

If you're looking to merge the arrays but also replace objects from padding with objects from data given the t value, this is one way:

const padding = [{'t': 1, 'c': 0}, {'t': 2, 'c': 0}, {'t': 3, 'c': 0}];
const data = [{'t': 3, 'c': 5}, {'t': 5, 'c': 6}];

const merged = [];

// loops through the objects in padding. If it finds an object in data that has the same t value, it chooses the object from data to add to the merged array. Otherwise, it uses the object from padding

padding.forEach((obj) => {
 	let dataObj = data.find(dataObj => dataObj.t === obj.t);
	if (dataObj) {
		merged.push(dataObj);
	} else {
		merged.push(obj);
	}
});

// loops through the data array. If there are any objects in data with a t value not in any padding object, it adds this to the merged array

data.forEach((obj) => {
	let paddingObj = padding.find(paddingObj => obj.t === paddingObj.t);
	if (!paddingObj) {
		merged.push(obj);
	}
});

console.log(merged);

1 Comment

Thanks for going extra mile. I guess I don’t need the “data” loop. I’d like to check the performance, I think optimisation will be needed. “data” should be subset of “padding”, but looping thru “padding” seems wasteful...the actual length of “padding” is 1000
1

You can use Map and map

  • First use Map to build a Map Object from data with t as key and c as value
  • Now loop over padding array and see if t is present is Map we use value of c from Map and else from current element only

const padding = [{'t': 1, 'c': 0}, {'t': 2, 'c': 0}, {'t': 3, 'c': 0}];
const data = [{'t': 3, 'c': 5}];

const mapper = new Map(data.map(( { t, c } ) => [t, c] ));

const final = padding.map(({ t, c }) => ({
    t,
    c: mapper.has(t) ? mapper.get(t) : c
}));

console.log(final);

1 Comment

If I change all format into array, wouldn't it be simpler? padding = [[1, 0], [2, 0], [3, 0]] and data = [[3, 5]] to get result = [[1, 0], [2, 0], [3, 5]]
0

I am not sure about efficiency but this piece of code works and is pretty readable

var padding = [{'t': 1, 'c': 0}, {'t': 2, 'c': 0}, {'t': 3, 'c': 0}]
var data = [{'t': 3, 'c': 5}, {'t': 4, 'c': 5}]

data.forEach(d => {
    padding.find(p => p.t === d.t).c = d.c
})

console.log(padding)
// OUTPUT: [ { t: 1, c: 0 }, { t: 2, c: 0 }, { t: 3, c: 5 } ]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.