To find object whereabouts in array of objects


#1
function whatIsInAName(collection, source) {

    var result = [];
    var arr1=Object.keys(source);
    console.log(arr1);

    for(var i=0;i<collection.length;i++){

    for(var j=0;j<arr1.length;j++){
      if(collection[i].hasOwnProperty(arr1[j])===false){ //Check 1 if false go to next object  in collection
        break;
      }
      else if(collection[i].hasOwnProperty(arr1[j])){
        console.log(source[arr1[j]],collection[i][arr1[j]])
        if(source[arr1[j]]!==collection[i][arr1[j]]){ //Check 2 if value is not equal break loop and goto next object in collection
          break;
        }
        continue; // if both check passes go for  next  property of source to check in object;
      }
      result.push(collection[i]); //if all values are present and checked in object push it in result array.
    }

    }

    return result;
    }

    console.log(whatIsInAName([{ “a”: 1, “b”: 2 }, { “a”: 1 }, { “a”: 1, “b”: 2, “c”: 2 }], { “a”: 1, “b”: 2 }));

Hey Guys I couldnt figure out the problem in my logic. I try to debug it even but cant find what the $%*$ is a problem with logic. The program is to Make a function that looks through an array of objects (first argument) and returns an array of all objects that have matching property and value pairs (second argument). Kindly help me over please.


#2

This is opinion, mind, but I find it rather clunky to compare anything to false. What is the intended action if not false?

if (obj[i].hasOwnProperty(prop) {
    // do something
} else {
    break;
}

Two things you could do to help yourself (and your readers)…

  1. Use shorter variable names (collection is a bit long).
  2. Use ample whitespace so operators and variables stand out.

Why afix a number to something when there is only one?

arr1  =>  arr

Quite often we see, obj to represent a collection (as you are calling it). A true collection in JavaScript is a DOM object that represents part of the document tree.

document.querySelectorAll('div');

would be such a collection.

Give the above notes some consideration and see it you cannot clean up your code so it’s easier to read and study for logic errors.


#3

I did it buts sir the problem is not in syntax or code. Its some kinda logic error I cant find.


#4

Can you show us your cleaned up code, please? Comments may be removed.


#5

function whatIsInAName(collection, source) {

var result = [];
var arr1=Object.keys(source);
console.log(arr1);

for(var i=0;i<collection.length;i++){

for(var j=0;j<arr1.length;j++){
 
 if(collection[i].hasOwnProperty(arr1[j])){ //check 1 if source and collection property matches 
    //console.log(source[arr1[j]],collection[i][arr1[j]])
    if(source[arr1[j]]!==collection[i][arr1[j]]){ //Check 2 if value is not equal break loop and goto next object in collection
      break;
    }
    continue; // if both check passes go for  next  property of source to check in object;
  }
  
  else { //check 1 if source and collection property not matches break the loop and goto next object in collection
    break;
  }
  result.push(collection[i]); //if all values are present and checked in object push it in result array.
}

}

return result;
}

console.log(whatIsInAName([{ a: 1, b: 2 }, { a: 1 }, { a: 1, b: 2, c: 2 }], { a: 1, b: 2 }));

#6

Okay, I feel kinda dumb going on about DOM objects. An array or objects must quality as a collection, too. D’uh! Blush.

Here is a thought experiment on what I assume is the objective…

let s = { a: 1, b: 2 };
let c = [{ a: 1 }, { a: 1, b: 2, c: 2 }, { a: 1, b: 2 }];

let i, x;

for (i = 0; i < c.length; i++) {
  let obj = c[i];
  for (let key in obj) {
    if (s.hasOwnProperty(key) && obj[key] === s[key]) {
      x = i;
    } else {
      x = false;
      break;
    }
  }
  if (x) break;
}

console.log(x, c[x], s)    //->  2 { a: 1, b: 2 } { a: 1, b: 2 }

See if there is anything in the above that can help with your logic.

It has a bug, though, and needs a way to tell if the collection object is shorter than the source object.

Debugged

let s = { a: 1, b: 2 };
let c = [{ a: 1 }, { a: 1 }, { a: 1 }, { a: 1, b: 2, c: 2 }, { a: 1, b: 2 }];

let sLength = Object.keys(s).length;

for (let i = 0, x; i < c.length; i++) {
  let obj = c[i];
  if (Object.keys(obj).length < sLength) continue;
  for (let key in obj) {
    if (s.hasOwnProperty(key) && obj[key] === s[key]) {
      x = i;
    } else {
      x = false;
      break;
    }
  }
  if (x) break;
}

console.log(x, c[x], s);    //->  4 { a: 1, b: 2 } { a: 1, b: 2 }

https://repl.it/MK5s


#7

What you are doing currently is that if all the if statements pass, and loops do not break anywhere, you put continue again at the last item of arr1. So, it goes to check next iteration, does not find it, and goes to next iteration in the collection loop. While doing this, it does not push any item to result.

Solution:

if(j !==(arr1.length - 1))
continue;

although thanks for helping :slight_smile:


#8

I still haven’t studied your code, beyond getting the gist of what the objective is. Rather my choice was to look at the problem fresh and hammer out a solution. That gives you something to compare with that may or may not coincide with your own logic.

Here is a functional approach to the object in an array problem…

const findObjectInArray = (haystack, needle) => {
  
  let needleSize = Object.keys(needle).length;
  let x;

  for (let i = 0; i < haystack.length; i++) {
    let obj = haystack[i];
    if (Object.keys(obj).length < needleSize) continue;
    for (let key in obj) {
      if (needle.hasOwnProperty(key) && obj[key] === needle[key]) {
        x = i;
      } else {
        x = false;
        break;
      }
    }
    if (x) break;
  }
  return x;
};

let s = { a: 1, b: 2 };
let c = [{ a: 1 }, { a: 1 }, { a: 1 }, { a: 1, b: 2, c: 2 }, { a: 1, b: 2 }];

console.log(result=findObjectInArray(c, s), c[result]);
//->  4 { a: 1, b: 2 }

https://repl.it/MK5s/1

Logic

Cache the length of the keys array of the needle object.

Iterate over haystack array; temp cache current object.

If the current object has less keys than the needle object, continue the outer loop.

Iterate over current object;

If needle has corresponding key and matching value, flag the index, otherwise set the flag to false and break out of inner loop

If the value of x is truthy (a number is truthy) then break out of outer loop.

Return the value of x (either an index, or false).