Reputation: 3657
I'm trying to figure out how to merge two arrays of objects. Here's what I need to do:
field
property is the unique identifier of each objectoriginalArray
localStorageArray
needs to be maintained, with attention paid to previous requirement (order should be: bar
, foo
, baz
)localStorageArray
: hidden
and width
(field
is a give-in, since its the identifier)originalArray
need to be maintained in outputHere's my wack at it:
outputArray.forEach(function(originalItem){
localStorageArray.forEach(function(localItem){
if(originalItem.field === localItem.field){
originalItem.hidden = localItem.hidden;
originalItem.width = localItem.width;
}
});
});
I was able to get the properties all right, but I'm a little lost on how to reorder according to localStorageArray
. I first thought to do so within the previous set of .forEach()
functions, but then I thought not to mess with the order within the forEach
loops, since I thought that might mess some things up.
Any suggestions to my solution?
Here are my arrays:
var originalArray = [{
field: "foo",
hidden: true,
sortable: false,
template: "<div>#=text#</div>",
width: "20px",
propA: "a",
propB: "b"
}, {
field: "bar",
hidden: false,
sortable: false,
template: "",
width: "20%",
propC: "C"
}, {
field: "baz",
hidden: false,
sortable: true,
template: "<span>#=text#</span>",
int: 3
}];
var localStorageArray = [{
field: "bar",
hidden: false,
sortable: false,
width: "100px"
}, {
field: "foo",
hidden: true,
sortable: false,
template: "<div>#=text#</div>",
width: "40px"
}, {
field: "boo",
hidden: true,
sortable: true,
template: "<div>Boo: #=text#</div>",
width: "200px"
}, {
field: "baz",
hidden: true,
template: "baz:#=text#",
width: "20px"
}];
And here is my desired output:
var desiredArray = [{
field: "bar",
hidden: false,
sortable: false,
template: "",
width: "100px",
propC: "C"
}, {
field: "foo",
hidden: true,
sortable: false,
template: "<div>#=text#</div>",
width: "40px",
propA: "a",
propB: "b"
}, {
field: "baz",
hidden: true,
sortable: true,
template: "<span>#=text#</span>",
width: "20px",
int: 3
}];
Upvotes: 1
Views: 76
Reputation: 23502
Here is an example using ES6 methods.
/*global document, console, expect */
(function () {
'use strict';
var originalArray = [{
field: 'foo',
hidden: true,
sortable: false,
template: '<div>#=text#</div>',
width: '20px',
propA: 'a',
propB: 'b'
}, {
field: 'bar',
hidden: false,
sortable: false,
template: '',
width: '20%',
propC: 'C'
}, {
field: 'baz',
hidden: false,
sortable: true,
template: '<span>#=text#</span>',
int: 3
}],
localStorageArray = [{
field: 'bar',
hidden: false,
sortable: false,
width: '100px'
}, {
field: 'foo',
hidden: true,
sortable: false,
template: '<div>#=text#</div>',
width: '40px'
}, {
field: 'boo',
hidden: true,
sortable: true,
template: '<div>Boo: #=text#</div>',
width: '200px'
}, {
field: 'baz',
hidden: true,
template: 'baz:#=text#',
width: '20px'
}],
desiredArray = [{
field: 'bar',
hidden: false,
sortable: false,
template: '',
width: '100px',
propC: 'C'
}, {
field: 'foo',
hidden: true,
sortable: false,
template: '<div>#=text#</div>',
width: '40px',
propA: 'a',
propB: 'b'
}, {
field: 'baz',
hidden: true,
sortable: true,
template: '<span>#=text#</span>',
width: '20px',
int: 3
}],
outputArray = [],
pre = document.getElementById('out'),
equalField = function (originalElement) {
return originalElement.field === this.field;
};
localStorageArray.reduce(function (acc, localElement) {
var original = originalArray.find(equalField, localElement),
shallowCopy;
if (original) {
shallowCopy = Object.assign({}, original);
shallowCopy.hidden = localElement.hidden;
shallowCopy.width = localElement.width;
acc.push(shallowCopy);
}
return acc;
}, outputArray);
try {
expect(outputArray).to.eql(desiredArray);
pre.textContent = 'outputArray is equal to desiredArray\n\n';
} catch (e) {
console.error(e);
pre.textContent = 'outputArray is not equal to desiredArray\n\n';
}
pre.textContent += JSON.stringify(outputArray, null, 2);
}());
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.32.0/es6-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/expect.js/0.2.0/expect.min.js"></script>
<pre id="out"></pre>
UPDATE: Based on your new comment and data, then this may be a solution.
var originalArray = [{
field: "foo",
hidden: true,
sortable: false,
template: "<div>#=text#</div>",
width: "20px",
propA: "a",
propB: "b"
}, {
field: "bee",
hidden: true,
sortable: false,
template: "=#text#",
int: 4
}, {
field: "bar",
hidden: false,
sortable: false,
template: "",
width: "20%",
propC: "C"
}, {
field: "baz",
hidden: false,
sortable: true,
template: "<span>#=text#</span>",
int: 3
}],
localStorageArray = [{
field: "bar",
hidden: false,
sortable: false,
width: "100px"
}, {
field: "foo",
hidden: true,
sortable: false,
template: "<div>#=text#</div>",
width: "40px"
}, {
field: "boo",
hidden: true,
sortable: true,
template: "<div>Boo: #=text#</div>",
width: "200px"
}, {
field: "baz",
hidden: true,
template: "baz:#=text#",
width: "20px"
}],
desiredArray = [{
field: "bar",
hidden: false,
sortable: false,
template: "",
width: "100px",
propC: "C"
}, {
field: "bee",
hidden: true,
sortable: false,
template: "=#text#",
int: 4
}, {
field: "foo",
hidden: true,
sortable: false,
template: "<div>#=text#</div>",
width: "40px",
propA: "a",
propB: "b"
}, {
field: "baz",
hidden: true,
sortable: true,
template: "<span>#=text#</span>",
width: "20px",
int: 3
}],
outputArray = [],
pre = document.getElementById('out'),
equalField = function (originalElement) {
return originalElement.field === this.field;
};
localStorageArray.reduce(function (acc, localElement) {
var original = originalArray.find(equalField, localElement),
shallowCopy;
if (original) {
shallowCopy = Object.assign({}, original);
shallowCopy.hidden = localElement.hidden;
shallowCopy.width = localElement.width;
acc.push(shallowCopy);
}
return acc;
}, outputArray);
originalArray.forEach(function (originalElement, index) {
if (!this.find(equalField, originalElement)) {
this.splice(index, 0, Object.assign({}, originalElement));
}
}, outputArray);
try {
expect(outputArray).to.eql(desiredArray);
pre.textContent = 'outputArray is equal to desiredArray\n\n';
} catch (e) {
console.error(e);
pre.textContent = 'outputArray is not equal to desiredArray\n\n';
}
pre.textContent += JSON.stringify(outputArray, null, 2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.32.0/es6-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/expect.js/0.2.0/expect.min.js"></script>
<pre id="out"></pre>
Upvotes: 1
Reputation: 1346
Check this fiddle: http://jsfiddle.net/j2u2hhk6/
You can actually do it like this:
var outputArray = [];
localStorageArray.forEach(function(localItem){
originalArray.forEach(function(originalItem){
if(originalItem.field === localItem.field){
var item = JSON.parse(JSON.stringify(originalItem));
item.hidden = localItem.hidden;
item.width = localItem.width;
outputArray.push(item);
}
});
});
Upvotes: 1