Reputation:
So I'm looking to achieve this in vanilla, ES6 JS. Please no jQuery! (Lodash is acceptable!)
Basically I have 2 arrays, 1 that contains objects, and 1 that contains ids.
const old = [
{
id: 1,
name: 'object_1',
},
{
id: 2,
name: 'object_2',
},
];
const newIds = [1, 2, 3];
My current solution to this problem is as shown;
const difference = newIds.filter(n => !old.some(o => o.id === n));
This results in the return [3]
.
Basically I'm currently using this to determine if something is missing, and create it in my database if it is missing.
However, I need to then do the opposite. If something is removed, I need to compare and remove the item.
The problem with this is; This current solution only works "1 way" so I'm unable to do what I stated above.
Ideally I only want 1 statement whether it's creation or deletion, and I only want it to return the id's of stuff that is missing from either array.
Hopefully that makes sense.
Upvotes: 3
Views: 1322
Reputation: 14
The following code will find the difference using lodash:
const difference = _.difference(newIds, _.map(old, 'id'));
Upvotes: 0
Reputation: 16908
We can do the same in vanilla es6 by using Array#filter
and Array#includes
.
Here, I have mapped the old array to only an array of ids by using Array#map
and then using the filter and includes on both the arrays I have found out the symmetric difference between them.
const old = [
{
id: 1,
name: 'object_1',
},
{
id: 2,
name: 'object_2',
},
];
const newIds = [2, 3];
const oldIds = old.map(({id}) => id);
console.log(getDifference(oldIds, newIds));
function getDifference(oldIds, newIds){
const diff = [...oldIds.filter(id => !newIds.includes(id)), ...newIds.filter(id => !oldIds.includes(id))];
return diff;
}
We can do it another way using Array#reduce
and Array#findIndex
. Just reduce over both the arrays and return the elements which are not repeated more than once will give us the symmetric difference of the two arrays.
const old = [
{
id: 1,
name: 'object_1',
},
{
id: 2,
name: 'object_2',
},
];
const newIds = [2, 3];
const oldIds = old.map(({id}) => id);
console.log(getDifference(oldIds, newIds));
function getDifference(oldIds, newIds){
return [...oldIds, ...newIds].reduce((acc, ele) => {
if(!acc.includes(ele)){
acc.push(ele);
}else{
acc.splice(acc.findIndex(e=> ele === e), 1);
}
return acc;
},[]);
}
Upvotes: 1
Reputation: 2575
You could use _.get
with a default value as an iteratee for _.differenceBy
so that either the array of objects or the array of numbers could be on the left hand side.
const old = [
{
id: 1,
name: 'object_1',
},
{
id: 2,
name: 'object_2',
},
];
const newIds = [1, 2, 3];
const diff = (a,b) => _.differenceBy(a, b, v => _.get(v, 'id', v))
console.log({ remove: diff(old, newIds), add: diff(newIds, old) })
const otherNewIds = [1];
console.log({ remove: diff(old, otherNewIds), add: diff(otherNewIds, old) })
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Upvotes: 0
Reputation: 1736
You can use xor
function from lodash to get this.
Before that, you can collect all the ids from the old
array and use that ids array for xor
.
Check this out.
const { xor } = _;
const old = [
{
id: 1,
name: 'object_1',
},
{
id: 2,
name: 'object_2',
},
{
id: 4,
name: 'object_4',
},
];
const newIds = [1, 2, 3];
const oldIds = old.map(o => o.id)
const diff = xor(newIds, oldIds);
console.log(diff)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Upvotes: 0
Reputation: 1780
Here is the solution using ES6:
const old = [
{
id: 1,
name: 'object_1',
},
{
id: 2,
name: 'object_2',
},
{
id: 4,
name: 'object_2',
},
];
const newIds = [1, 2, 3];
const oldIds = old.map(o => o.id)
const difference = [...newIds.filter(id => oldIds.indexOf(id) === -1), ...oldIds.filter(id => newIds.indexOf(id) === -1)]
console.log(difference)
Upvotes: 0
Reputation: 88378
To find the values that appear in one but not the other use lodash's
_.xor(array1, array2);
In your case:
> const _ = require('lodash');
> const old = [
... { id: 1, name: 'object_1' },
... { id: 2, name: 'object_2' },
... { id: 3, name: 'object_3' },
... { id: 4, name: 'object_4' },
... ];
> const newIds = [1, 3, 5, 7];
> _.xor(old.map(x => x.id), newIds)
[ 2, 4, 5, 7 ]
Upvotes: 5
Reputation: 2941
Hope this helps. I know this not excatly what you want, but this can be one work around.
const old = [
{
id: 1,
name: 'object_1',
},
{
id: 2,
name: 'object_2',
},
{
id: 4,
name: 'object_2',
},
];
const newIds = [1, 2, 3];
var x1 = old.filter(x => !newIds.includes(x.id)).map(z => z.id)
.concat(newIds.filter(x => !old.some(y => y.id === x)));
console.log(x1);
Upvotes: 0