Reputation: 5326
I've already solved this out. However I'm looking for a faster solution since my variables has thousands of objects.
I have two arrays like this:
var full = [{a:'aa1',b:'bb1'},{a:'aa3',b:'bb2'},{a:'aa3',b:'bb3'},{a:'aa2',b:'bb3'}],
some = [{a:'aa1',b:'bb1'},{a:'aa3',b:'bb3'}];
I'm trying to flag in a new attribute called c
in full
if the object exist on some. Expected result:
[{a:'aa1',b:'bb1',c:true},{a:'aa3',b:'bb2'},{a:'aa3',b:'bb3',c:true},{a:'aa2',b:'bb3'}]
Some important tips:
My current approach is:
var getIndexByAB = function(arr, a,b){
var initialIndex = getIndexByAB.initialIndex || 0,
len = arr.length;
for(initialIndex; initialIndex < len ;initialIndex++ ){
var el = arr[initialIndex];
if( el.b === b && el.a === a ){
getIndexByAB.initialIndex = initialIndex;
return initialIndex;
}
}
return -1;
}
var len = some.length;
for(var i = 0; i < len ; i++){
var el=some[i],
index = getIndexByAB(full,el.a,el.b);
if(index > -1) full[index].c = true;
}
UPDADE: original solution improved using Juan comment.
Upvotes: 1
Views: 1224
Reputation: 16456
Not as efficient as @Juan's answer (which takes advantage of the sorted nature, among other things), but I thought I'd still present my solution as it incidentally forced me to come up with a solution for cloning and comparing Javacript objects.
// Create a copy of x without reference back to x
function clone(x){
return JSON.parse(JSON.stringify(x));
}
// Pass any number of arguments of any type. Returns true if they are all identical.
function areEqual(){
for(var i = 1, l = arguments.length, x = JSON.stringify(arguments[0]); i < arguments.length; ++i){
if(x !== JSON.stringify(arguments[i])){
return false;
}
}
return true;
}
// Your flagLabel being 'c'
function matchAndFlagWith(flagLabel,aFull,aSome){
var aFlagged = clone(aFull);
for(var i1 = 0, l1 = aSome.length, oSome; oSome = aSome[i1], i1 < l1; ++i1){
for(var i2 = 0, l2 = aFlagged.length, oFlagged; oFlagged = aFlagged[i2], i2 < l2; ++i2){
if(areEqual(oFlagged,oSome)){
oFlagged[flagLabel] = true;
}
}
}
return aFlagged;
}
http://jsfiddle.net/barney/p2qsG/
Upvotes: 0
Reputation: 92274
Since they are sorted, you can just pass an index to start the search from, that will avoid the O(n^2). You were already doing it, but by storing the index in a global variable. Instead, you should pass it as an argument to getIndexByAB
.
function getIndexByAB(arr, a,b , initialIndex){
// Was tracking last index by storing it in a global 'this.initialIndex'.
// 'this' points to 'window' in global functions. That's bad, it
// means this function can't be called on different arrays without
// resetting the global
// var initialIndex = this.initialIndex || 0,
initialIndex = initialIndex || 0;
var len = arr.length;
for(initialIndex; initialIndex < len ; initialIndex++ ){
var el = arr[initialIndex];
if( el.b === b && el.a === a ){
// Bad globals
// this.initialIndex = initialIndex;
return initialIndex;
}
}
return -1;
}
var len = some.length;
var lastValidIndex = 0;
for(var i = 0; i < len ; i++){
var el = some[i];
// Pass the index here, so it doesn't start from scratch
var index = getIndexByAB(full, el.a, el.b, lastValidIndex);
if(index > -1) {
full[index].c = true;
lastValidIndex = index;
}
}
By the way, if you do want a function to cache some values, here's how to do it avoiding globals. (Not that you should use it in this case)
var getIndexByAB = (function(){
// This will only be executed once, and is private
// to getIndexByAB (all invocations)
var lastGoodIndex = 0;
return function(arr, a,b, resetIndex){
if (resetIndex) {
lastGoodIndex = 0;
}
var len = arr.length;
for(var index = lastGoodIndex; index < len ; index++ ){
var el = arr[index];
if( el.b === b && el.a === a ){
lastGoodIndex = index;
return index;
}
}
return -1;
};
})();
Alternatively, you could achieve the following by caching it in getIndexByAB.initialIndex
but it's not very elegant. The main reason for avoiding this is the fact that getIndexByAB.initialIndex
can be modified by anybody else
Upvotes: 1
Reputation: 5930
Since the arrays are both sorted and some
is strictly smaller than full
, you could save some time by traversing both arrays at the same time with different indexes. As it is, you are traversing full
to get the index of the matching element each time, so you have O(N^2) running time, but you only need to continue the search from the last element you matched.
Upvotes: 0