Suppose i have an array of objects like this
let arr = [
{
abcdef: {name: 'Robin', uid: '123'},
ghijkl: {name: 'Simon', uid: '456'}
},
{
mnopqr: {name: 'Alex', uid: '789'},
abcdef: {name: 'Robin', uid: '123'}
},
{
abcdef: {name: 'Robin', uid: '123'},
stuvwx: {name: 'Julianna', uid: '111'},
yzxwuv: {name: 'Elon', uid: '007'}
}
];
In position of arr[0]
, arr[1]
and arr[2]
, i define a object and inside that object, i define couple of objects.
Here this abcdef: {name: 'Robin', uid: '123'}
is common among the three(arr[0], arr[1], arr[2]). So i need to write a function that returns the common one.
In this case abcdef: {name: 'Robin', uid: '123'}
UPDATE: If there is nothing in common, return false. And two or more in common, return all of them.
You can easily do that by using intersectionWith
- it accepts a custom comparator for your elements. The easiest way is to convert the object into an array of entries using toPairs
and then compare those with isEqual
. The intersection would then be an array containing pairs of attribute and value, so you can then convert it back to an object using fromPairs
let arr = [
{
abcdef: {name: 'Robin', uid: '123'},
ghijkl: {name: 'Simon', uid: '456'}
},
{
mnopqr: {name: 'Alex', uid: '789'},
abcdef: {name: 'Robin', uid: '123'}
},
{
abcdef: {name: 'Robin', uid: '123'},
stuvwx: {name: 'Julianna', uid: '111'},
yzxwuv: {name: 'Elon', uid: '007'}
}
];
const inputPairs = arr.map(_.toPairs);
const resultPairs = _.intersectionWith(...inputPairs, _.isEqual);
const resultObject = _.fromPairs(resultPairs);
console.log(resultObject);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
Using chaining this can be written as:
let arr = [ { abcdef: {name: 'Robin', uid: '123'}, ghijkl: {name: 'Simon', uid: '456'} }, { mnopqr: {name: 'Alex', uid: '789'}, abcdef: {name: 'Robin', uid: '123'} }, { abcdef: {name: 'Robin', uid: '123'}, stuvwx: {name: 'Julianna', uid: '111'}, yzxwuv: {name: 'Elon', uid: '007'} } ];
const resultObject = _(arr)
.map(_.toPairs)
.thru(pairs => _.intersectionWith(...pairs, _.isEqual))
.fromPairs()
.value();
console.log(resultObject);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
Using thru
here because the chain contains an array with other array in it and each needs to be passed as a separate argument to intersectionWith
. It's the easiest way to do that.
Alternatively, if you prefer a more FP approach then it can look like this:
const {spread, intersectionWith, isEqual, flow, map, toPairs, fromPairs} = _;
let arr = [ { abcdef: {name: 'Robin', uid: '123'}, ghijkl: {name: 'Simon', uid: '456'} }, { mnopqr: {name: 'Alex', uid: '789'}, abcdef: {name: 'Robin', uid: '123'} }, { abcdef: {name: 'Robin', uid: '123'}, stuvwx: {name: 'Julianna', uid: '111'}, yzxwuv: {name: 'Elon', uid: '007'} } ];
const process = flow(
map(toPairs),
spread(intersectionWith(isEqual)),
fromPairs
);
const resultObject = process(arr);
console.log(resultObject);
<script src="https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)"></script>