Check if javascript object has nested key-value pairs

Viewed 229

I have an object being returned that I don't know the structure of beforehand. The only thing I know is what values should be in the object. My goal isn't to check whether or not the returned object specifically matches another, but to check whether specific nested key-value pairs exist in the returned object.

The following is a random object that I could expect to be returned and the values that I want to check for. Is there anything out there already written that performs this type of check? Sorry for the lack of code, but I'm not sure where to really begin with this. I thought about maybe flattening the objects and doing a check, but due to unknown array lengths that idea didn't pan out.

// ob1 is the random object being returned. This will not be the same every time.
ob1 = {
    key_a: "val_a1",
    key_b: [
        "val_b1",
        "val_b2",
        "val_b3"
    ]
}

ob2a = {
    key_b: [
        "val_b2"
    ]
}

ob2b = {
    key_a: "val_a1",
    key_b: [
        "val_b3"
    ]
}

ob2c = {
    key_b: [
        "val_b2"
        "val_b3"
    ]
}

ob2d = {
    key_b: [
        "val_b1",
        "val_doesnt exist"
    ]
}

ob2e = {
    key_b: "val_b1"
}

checkExists(ob1,ob2a) // true
checkExists(ob1,ob2b) // true
checkExists(ob1,ob2c) // true
checkExists(ob1,ob2d) // false
checkExists(ob1,ob2e) // false
2 Answers

If I understood you correctly in your example ob1 is the object you want to compare each of the other ob2a, ..., ob2e.

This is what I came up with:

const checkExists = (ob1, ob2) => {
    // Filter for only matched keys between the two objects
    const matchedKeys = Object.keys(ob1).filter(key => {
        if(ob2[key] !== undefined) return key;
    });

    // No matched keys found so there are no nested key-value pairs 
    if(matchedKeys.length === 0) return false;
    else {
        let result = true;
        matchedKeys.forEach(key => {
            const ob1CurrentValue = ob1[key];
            const ob2CurrentValue = ob2[key];

            // Case: both values are arrays
            if(Array.isArray(ob1CurrentValue) && (Array.isArray(ob2CurrentValue))) {
                ob2CurrentValue.forEach(value => {
                    // If 1 value is not found result is false
                    if(!ob1CurrentValue.includes(value)) {
                        result = false;
                    }
                });
            // Case: both values are objects
            } else if(typeof ob1CurrentValue === 'object' && typeof ob2CurrentValue === 'object') {
                result = result && checkExists(ob1[key], ob2[key]);
            } else {
                result = ob1CurrentValue === ob2CurrentValue;
            }
        });

        return result;
    }
}

const ob1 = {key_a: "val_a1", key_b: ["val_b1", "val_b2", "val_b3"]};
const ob2a = {key_b: ["val_b2"]};
const ob2b = {key_a: "val_a1", key_b: ["val_b3"]};
const ob2c = {key_b: ["val_b2","val_b3"]};
const ob2d = {key_b: ["val_b1", "val_doesnt exist"]};
const ob2e = {key_b: "val_b1"};
const ob2f = {key_c: "val_c1"};
const ob2g = {key_c: "val_c1", key_b: "val_b1"};
const ob2h = {key_c: "val_b1", key_b: "val_b1"};
const ob2i = {key_a: "val_a1", key_b: ["val_b1", "val_b2", "val_b3"], key_c: { key_c1: ["val_c1_1"], key_c2: ["val_c2_1"]}};
const ob2j = {key_c: {key_c1: ["val_c1_1"]}};
const ob2k = {key_a: "val_a11"};
const objl = {key_a: "val_a11", key_c: {"key_c1":["val_c1_1"]}};

console.log(checkExists(ob1, ob2a)); // true
console.log(checkExists(ob1, ob2b)); // true
console.log(checkExists(ob1, ob2c)); // true
console.log(checkExists(ob1, ob2d)); // false
console.log(checkExists(ob1, ob2e)); // false
console.log(checkExists(ob1, ob2f)); // false
console.log(checkExists(ob1, ob2g)); // false
console.log(checkExists(ob1, ob2h)); // false
console.log(checkExists(ob2i, ob2j)); // true
console.log(checkExists(ob2i, ob2k)); // false
console.log(checkExists(ob2i, objl)); // false

What I did is first look for only matched keys between compared objects, if there are matched ones I check if ob1 contain all values of ob2 for each key.

Also I tried covering more cases like:

ob2f = {
    key_c: "val_c1"
}

ob2g = {
    key_c: "val_c1",
    key_b: "val_b1"
}

ob2h = {
    key_c: "val_b1",
    key_b: "val_b1"
}

I do not know if those are relevant for you.

    function checkIfExists(list1, list2) {
      let output = list2.filter(a=>!list1.some(b=>a==b))
      if(output.length==0) {
        return true;
      }
      return false
    }

   console.log(checkIfExists(ob1.key_b, ob2b.key_b))

You can add checks whether ob2b.key_b exists and is array or not. Please note that, as per your question, it will work only in case of array.

Related