Reputation: 71
OK so I've already actually figured out a solution to my problem, but it's ugly, and I'm sure there's a much more elegant way to do it.
Say I've got two arrays (which I know to be of the same length), of simple objects, like this:
var aVals = [{a: 1}, {a: 2}, {a: 3}];
var bVals = [{b: 4}, {b: 5}, {b: 6}];
What I want to do is squash these two arrays together, so to speak, to get something that looks like this:
var allVals = [{a: 1, b: 4},{a: 2, b: 5},{a: 3, b: 6}];
Granted, I can do that like this:
var uglySolution = [];
for(var i = 0; i < aVals.length; i++){
var temp = [];
temp.push(aVals[i]);
temp.push(bVals[i]);
uglySolution.push(Object.assign({}, ...temp));
}
console.log(uglySolution);
But there's got to be a better way! Right?
*Bonus quest: and what if I couldn't be sure both arrays were the same length?
Upvotes: 1
Views: 101
Reputation: 33726
You can use the function Array.from
.
var aVals = [{a: 1}, {a: 2}, {a: 3}];
var bVals = [{b: 4}, {b: 5}, {b: 6}, {a: 4}];
var merge = Array.from({length: Math.max(aVals.length, bVals.length)}, (_, i) => {
return Object.assign({}, bVals[i] || {}, aVals[i] || {});
});
console.log(merge)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 386520
You could collect all arrays with the data and use an approach which works for an arbitrary count of given arrays with objects and length.
var merge = (r, a) => (a.forEach((o, i) => Object.assign(r[i] = r[i] || {}, o)), r)
aVals = [{ a: 1 }, { a: 2 }, { a: 3 }],
bVals = [{ b: 4 }, { b: 5 }, { b: 6 }],
result = [aVals, bVals].reduce(merge, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 10975
To achieve expected result use forEach method with array destructuring and it works for any array length
var aVals = [{a: 1}, {a: 2}];
var bVals = [{b: 4}, {b: 5}, {b: 6}];
var allVals = []
var func = (arr) => arr.forEach(function(element,index) {
allVals[index] = {...allVals[index],...arr[index]}
});
func(aVals);
func(bVals);
console.log(allVals)
code sample - https://codepen.io/pen/?editors=1010
Upvotes: 0
Reputation: 32146
I think your solution is fine. It works and it's readable, so I'd say there's no need for a "better solution". However, if you're looking for something shorter, you can definitely compress your code a bit.
Here's one way of doing so that uses array destructuring and object spread. Just take the longer array, and map each of it's items to the combo of that item and the item in the same position in the other array.
var aVals = [{a: 1}, {a: 2}, {a: 3}];
var bVals = [{b: 4}, {b: 5}, {b: 6}, {b: 7}];
// var allVals = [{a: 1, b: 4},{a: 2, b: 5},{a: 3, b: 6}];
function zipArrays(arr1, arr2) {
// Swap if arr2 is longer, so that on the next line, arr1 is always longer
if (arr2.length > arr1.length) [arr1, arr2] = [arr2, arr1];
return arr1.map((o, i) => ({...o, ...arr2[i]}));
}
console.log(zipArrays(aVals, bVals))
Upvotes: 0
Reputation: 3130
You could use ES6 and do something like this.
var aVals = [{
a: 1
}, {
a: 2
}, {
a: 3
}];
var bVals = [{
b: 4
}, {
b: 5
}, {
b: 6
}, {
b: 7
}];
const mergeArrays = (obj1, obj2) => {
if (obj1.length > obj2.length) {
[obj1, obj2] = [obj2, obj1];
}
const output = obj1.map((value, index) => {
return {
...value,
...obj2[index]
};
});
return output.concat(obj2.slice(obj1.length, obj2.length));
}
console.log(mergeArrays(aVals, bVals));
Upvotes: 0
Reputation: 869
You could one line what's in the for loop like this:
var uglySolution = [];
for(var i = 0; i < aVals.length; i++){
uglySolution.push(Object.assign({}, aVals[i], bVals[i]))
}
console.log(uglySolution);
Assuming both arrays are the same size.
If they are NOT the same size, do this:
var uglySolution = [];
var longestLength = aVals.length > bVals.length ? aVals.length : bVals.length;
for(var i = 0; i < longestLength; i++){
uglySolution.push(Object.assign({}, aVals[i] || {} , bVals[i] || {}))
}
console.log(uglySolution);
Upvotes: 0
Reputation: 452
If you have arrays of the same length it's simple:
var aVals = [{a: 1}, {a: 2}, {a: 3}];
var bVals = [{b: 4}, {b: 5}, {b: 6}];
var result = aVals.map((el, i) => Object.assign({}, el, bVals[i]));
console.log(result);
To do it with different array length I'd do it like this:
var aVals = [{a: 1}, {a: 2}];
var bVals = [{b: 4}, {b: 5}, {b: 6}];
var result = [];
var length = Math.max(aVals.length, bVals.length);
for (var i = 0; i < length; i++) {
result.push(Object.assign({}, aVals[i] || {}, bVals[i] || {}));
}
console.log(result);
Upvotes: 2
Reputation: 7553
This would be a bit better, I think.
var aVals = [{a: 1}, {a: 2}, {a: 3}];
var bVals = [{b: 4}, {b: 5}, {b: 6}];
var result = aVals.map((val, index) => Object.assign(val, bVals[index]));
console.log(result);
Upvotes: 0
Reputation: 1392
You can get rid of the temp var and the uglySolution var.
for (var i = 0; i < bVals.length; i++) {
aVals.push(bVals.pop())
}
console.log(aVals);
This simplifies it into one var being used and only a small loop.
Upvotes: 0