I am getting two array of objects from the server like this:
var duplicateTestData = [
{
licenseId: 'xxx',
batchId: '123',
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)
},
{
licenseId: 'yyy',
batchId: '124',
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)
},
{
licenseId: 'aaa',
batchId: '145',
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)
}
];
var finalResult = [
{
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time),
license: {},
testType: 'P1',
productType: 'Flower',
batchId: '123',
licenseId: 'xxx',
createType: 'DataUpload'
},
{
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time),
testType: 'P1',
productType: 'Flower',
batchId: '124',
licenseId: 'yyy',
createType: 'DataUpload'
},
{
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time),
testType: 'P1',
productType: 'Flower',
batchId: '145',
licenseId: 'aaa',
createType: 'DataUpload'
},
{
reportDate: Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time),
testType: 'P1',
productType: 'Flower',
batchId: '145',
licenseId: 'zzz',
createType: 'DataUpload'
}
]
I am trying to fetch only unmatched objects from the finalResult
object, the final result would be like this:
[
{
reportDate: Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time),
testType: 'P1',
productType: 'Flower',
batchId: '145',
licenseId: 'zzz',
createType: 'DataUpload'
}
]
I am trying this, but am not getting the right result:
for(var j=0;j < duplicateTestData.length;j++){
for (var i = 0; i < finalResult.length; i++) {
if (
(finalResult[i].licenseId == duplicateTestData[j].licenseId) &&
(finalResult[i].reportDate == duplicateTestData[j].reportDate) &&
(finalResult[i].batchId == duplicateTestData[j].batchId)
) {
finalResult.splice(i, 1);
break;
}
}
}
console.log(finalResult);
I am getting two array of objects from the server like this:
var duplicateTestData = [
{
licenseId: 'xxx',
batchId: '123',
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)
},
{
licenseId: 'yyy',
batchId: '124',
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)
},
{
licenseId: 'aaa',
batchId: '145',
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)
}
];
var finalResult = [
{
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time),
license: {},
testType: 'P1',
productType: 'Flower',
batchId: '123',
licenseId: 'xxx',
createType: 'DataUpload'
},
{
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time),
testType: 'P1',
productType: 'Flower',
batchId: '124',
licenseId: 'yyy',
createType: 'DataUpload'
},
{
reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time),
testType: 'P1',
productType: 'Flower',
batchId: '145',
licenseId: 'aaa',
createType: 'DataUpload'
},
{
reportDate: Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time),
testType: 'P1',
productType: 'Flower',
batchId: '145',
licenseId: 'zzz',
createType: 'DataUpload'
}
]
I am trying to fetch only unmatched objects from the finalResult
object, the final result would be like this:
[
{
reportDate: Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time),
testType: 'P1',
productType: 'Flower',
batchId: '145',
licenseId: 'zzz',
createType: 'DataUpload'
}
]
I am trying this, but am not getting the right result:
for(var j=0;j < duplicateTestData.length;j++){
for (var i = 0; i < finalResult.length; i++) {
if (
(finalResult[i].licenseId == duplicateTestData[j].licenseId) &&
(finalResult[i].reportDate == duplicateTestData[j].reportDate) &&
(finalResult[i].batchId == duplicateTestData[j].batchId)
) {
finalResult.splice(i, 1);
break;
}
}
}
console.log(finalResult);
Share
Improve this question
edited Aug 18, 2016 at 9:54
DrakaSAN
7,8538 gold badges56 silver badges96 bronze badges
asked Aug 18, 2016 at 5:56
RockRock
75814 silver badges39 bronze badges
6
- 2 what constitutes a match ? – Mulan Commented Aug 18, 2016 at 6:01
- @naomik i am trying to match all the properties of first object with the second object properties. – Rock Commented Aug 18, 2016 at 6:04
- I put your code in a fiddle at jsfiddle.net/kjdx6e4o looks ok to me. Did I miss something? – Dhananjay Commented Aug 18, 2016 at 6:07
- @Dhananjay the fiddle is working. I dont understand what is the problem – Kaushal Niraula Commented Aug 18, 2016 at 6:10
- 1 @Jeevan Without the quotes, the data is not valid JSON, perhaps this needs to be fixed on the server ? – Dhananjay Commented Aug 18, 2016 at 6:25
5 Answers
Reset to default 8the easy way out
finalResult.filter(({batchId:a, licenseId:b, reportDate:c}) =>
duplicateTestData.find(({batchId:x, licenseId:y, reportDate:z}) =>
a === x && b === y && c === z) === undefined)
=> [ { reportDate: 'Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time)',
testType: 'P1',
productType: 'Flower',
batchId: '145',
licenseId: 'zzz',
createType: 'DataUpload' } ]
OK, it works, but this is mostly garbage. It doesn't completely and accurately describe the comparison you're trying to make. It's way too specific and it will break as soon as something about your data changes.
Keep reading and we can learn something fun.
object equality for all (keys and values) …
I would begin by making several generic procedures that we can use to better describe the solution to our problem.
What you'll notice about this solution compared to others is that it makes no assumptions about the internals of your data. This solution couldn't care less about the actual key names used in your objects.
That means we won't be touching any batchId
, licenseId
, or reportDate
. Generic procedures can solve everything in this case and the best part about that is you can use them over and over again on any data you wish to process.
// arrayCompare :: (a -> b -> Bool) -> [a] -> [b] -> Bool
const arrayCompare = f=> ([x,...xs])=> ([y,...ys])=> {
if (x === undefined && y === undefined)
return true
else if (! f (x) (y))
return false
else
return arrayCompare (f) (xs) (ys)
}
// keys :: Object(k:v) -> [k]
const keys = Object.keys
// objectCompare :: (v -> v -> Bool) -> Object(k:v) -> Object(k:v) -> Bool
const objectCompare = f=> a=> b=>
arrayCompare (x=> y=> f (a[x]) (b[y]) && f (a[y]) (b[y])) (keys(a)) (keys(b))
// objectEqual :: Object -> Object -> Bool
const objectEqual = objectCompare (x=> y=> x === y)
// sample data
let xs = [
{a:1,b:10},
{a:2,b:20},
{a:3,b:30}
]
let ys = [
{a:1,b:10},
{a:2,b:20},
{a:3,b:30},
{a:4,b:40}
]
// return all ys that are not present in xs
var result = ys.filter(y=> xs.find(objectEqual(y)) === undefined)
console.log(result)
// [{a:4,b:40}]
gotcha !
You will have to adjust this solution somewhat because you're not comparing all object keys. Objects in finalResult
have more keys than objects in duplicateTestData
so there are zero 1:1 matches.
In simpler words, you want x = {a:1}
to be considered a "match" if it is compared against y = {a:1,b:2}
, so long as all key:values in x
match all key:values in y
If we used the objectEquals
comparator above, nothing would be filtered out of finalResult
because no object would match an object found in duplicateTestData
. Since this is not what you want, let's define a comparator that works for your case …
// subsetObjectEquals :: Object -> Object -> Bool
const subsetObjectEquals = objectCompare (x=> y=> y === undefined || x === y)
// this time use subsetObjectEquals
var result = finalResult.filter(x=>
duplicateTestData.find(subsetObjectEquals(x)) === undefined)
subsetObjectEquals
works a bit differently. I couldn't really think of a better name because this is a somewhat strange comparison. When y
is undefined
, it means the key for that value is not present in the "subset object" and therefore does not need to be compared
subsetObjectEquals(a,b)
// returns true if all key:value pairs in `a` match all key:value pairs in `b`
// otherwise returns false
full working example
I've attached a full snippet that actually uses the input data included in your question. Expand it here and run it to see it work
// arrayCompare :: (a -> b -> Bool) -> [a] -> [b] -> Bool
const arrayCompare = f=> ([x,...xs])=> ([y,...ys])=> {
if (x === undefined && y === undefined)
return true
else if (! f (x) (y))
return false
else
return arrayCompare (f) (xs) (ys)
}
// keys :: Object(k:v) -> [k]
const keys = Object.keys
// objectCompare :: (v -> v -> Bool) -> Object(k:v) -> Object(k:v) -> Bool
const objectCompare = f=> a=> b=>
arrayCompare (x=> y=> f (a[x]) (b[x]) && f (a[y]) (b[y])) (keys(a)) (keys(b))
// objectEqual :: Object -> Object -> Bool
const objectEqual = objectCompare (x=> y=> x === y)
// subsetObjectEquals :: Object -> Object -> Bool
const subsetObjectEquals = objectCompare (x=> y=> y === undefined || x === y)
// your data
var duplicateTestData = [{ licenseId: 'xxx',
batchId: '123',
reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)' },
{ licenseId: 'yyy',
batchId: '124',
reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)' },
{ licenseId: 'aaa',
batchId: '145',
reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)' }
];
var finalResult = [ { reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)',
license: {},
testType: 'P1',
productType: 'Flower',
batchId: '123',
licenseId: 'xxx',
createType: 'DataUpload' },
{ reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)',
testType: 'P1',
productType: 'Flower',
batchId: '124',
licenseId: 'yyy',
createType: 'DataUpload' },
{ reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)',
testType: 'P1',
productType: 'Flower',
batchId: '145',
licenseId: 'aaa',
createType: 'DataUpload' },
{ reportDate: 'Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time)',
testType: 'P1',
productType: 'Flower',
batchId: '145',
licenseId: 'zzz',
createType: 'DataUpload' }
]
// get all finalResult items that do not subsetObjectEqual items in duplicateTestData
var result = finalResult.filter(x=>
duplicateTestData.find(subsetObjectEquals(x)) === undefined)
console.log(result)
var res = _.filter(finalResult, function(item) {
return !_.find(duplicateTestData, {
batchId: item.batchId,
licenseId: item.licenseId,
reportDate: item.reportDate
});
});
console.log(res);
jsfiddle
You could use a hash table and return a new result set, without the problem of splicing an array while iterating it.
function getKey(o) {
return o.licenseId + '|' + o.reportDate + '|' + o.batchId;
}
var duplicateTestData = [{ licenseId: 'xxx', batchId: '123', reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)' }, { licenseId: 'yyy', batchId: '124', reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)' }, { licenseId: 'aaa', batchId: '145', reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)' }],
finalResult = [{ reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)', license: {}, testType: 'P1', productType: 'Flower', batchId: '123', licenseId: 'xxx', createType: 'DataUpload' }, { reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)', testType: 'P1', productType: 'Flower', batchId: '124', licenseId: 'yyy', createType: 'DataUpload' }, { reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)', testType: 'P1', productType: 'Flower', batchId: '145', licenseId: 'aaa', createType: 'DataUpload' }, { reportDate: 'Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time)', testType: 'P1', productType: 'Flower', batchId: '145', licenseId: 'zzz', createType: 'DataUpload' }],
hash = Object.create(null),
result = [];
duplicateTestData.forEach(function (a) {
hash[getKey(a)] = true;
});
result = finalResult.filter(function (a) {
return !hash[getKey(a)];
});
console.log(result);
ES6
function getKey(o) {
return o.licenseId + '|' + o.reportDate + '|' + o.batchId;
}
var duplicateTestData = [{ licenseId: 'xxx', batchId: '123', reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)' }, { licenseId: 'yyy', batchId: '124', reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)' }, { licenseId: 'aaa', batchId: '145', reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)' }],
finalResult = [{ reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)', license: {}, testType: 'P1', productType: 'Flower', batchId: '123', licenseId: 'xxx', createType: 'DataUpload' }, { reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)', testType: 'P1', productType: 'Flower', batchId: '124', licenseId: 'yyy', createType: 'DataUpload' }, { reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)', testType: 'P1', productType: 'Flower', batchId: '145', licenseId: 'aaa', createType: 'DataUpload' }, { reportDate: 'Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time)', testType: 'P1', productType: 'Flower', batchId: '145', licenseId: 'zzz', createType: 'DataUpload' }],
map = duplicateTestData.reduce((r, a) => r.set(getKey(a)), new Map),
result = finalResult.filter(a => !map.has(getKey(a)));
console.log(result);
for (var a = 0; a < duplicateTestData.length; a++) {
var dt = duplicateTestData[a];
var dtr = new Date(dt.reportDate + '');
for (var b = 0; b < finalResult.length; b++) {
var fr = finalResult[b];
var frr = new Date(fr.reportDate + '');
//define your logic how to match two objects
if (dtr.getTime() !== frr.getTime() &&
dt.batchId !== fr.batchId) {
//object matched. remove it from array
var removed = finalResult.splice(b, 1);
console.log('items removed', removed);
}
}
}
//print finalResult array
for (var c = 0; c < finalResult.length; c++) {
console.log(finalResult[c]);
}
Using lodash:
duplicateTestData.reduce( _.reject, finalResult );
var duplicateTestData = [
{
licenseId: 'xxx',
batchId: '123',
reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)'
},
{
licenseId: 'yyy',
batchId: '124',
reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)'
},
{
licenseId: 'aaa',
batchId: '145',
reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)'
}
];
var finalResult = [
{
reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)',
license: {},
testType: 'P1',
productType: 'Flower',
batchId: '123',
licenseId: 'xxx',
createType: 'DataUpload'
},
{
reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)',
testType: 'P1',
productType: 'Flower',
batchId: '124',
licenseId: 'yyy',
createType: 'DataUpload'
},
{
reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)',
testType: 'P1',
productType: 'Flower',
batchId: '145',
licenseId: 'aaa',
createType: 'DataUpload'
},
{
reportDate: 'Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time)',
testType: 'P1',
productType: 'Flower',
batchId: '145',
licenseId: 'zzz',
createType: 'DataUpload'
}
]
console.log( duplicateTestData.reduce( _.reject, finalResult ) );
<script src="https://cdn.jsdelivr.net/lodash/4.15.0/lodash.min.js"></script>
The core of this is _.reject()
, which is the opposite of _.filter()
: when passed an object it will use _.matches()
to do a partial comparison.
To run it for each of the entries in duplicateTestData we can use .reduce()
, the standard Array function. We pass in finalResult as the initialValue. Conveniently the arguments are in the right order, so we don't need an anonymous function! (I should really say that lodash is a very well designed library.) Once reduce()
has run through all the entries in duplicateTestData it will return the final filtered result.