I have a Javascript object that can have either none, one, or multiple keys. Then each key has a nested value.
Example
cart = {
"98eb9514-f403-4d08-b5f7-dd6a5ec013cb": {
"quantity": 1,
"FirstName": "John",
"LastName": "Lewis"
},
"92ef2918-6bc2-4f3b-b9b3-acf6ebe74b1f": {
"quantity": 1,
"FirstName": "Matthew",
"LastName": "Smith"
}
}
I need to check if a key has an exact nested value. If it does, then I need to add 1 to the quantity for that exact key with that exact nested value.
I am able to check if an exact key with that exact nested value exist by doing:
if (cart.hasOwnProperty(productId) &&
cart[productId]["quantity"] >= 1 &&
cart[productId]["FirstName"] == FirstName &&
cart[productId]["LastName"] == LastName) {
console.log('add one to qty somehow...')
}
However, this seems very inefficient and then I can't even figure out a way to add one to the quantity for just that exact key with that exact nested value.
If it is not clear, my question comes down to this: How do I check if a key with an exact nested value exist, and if it does, how do I add 1 to the quantity for that same exact key/nested value.
Been working on this for a day and half. Any help is much appreciated.
You could do it like this:
const cart = {
"98eb9514-f403-4d08-b5f7-dd6a5ec013cb":{"quantity":1,"FirstName":"John", "LastName":"Lewis"},
"92ef2918-6bc2-4f3b-b9b3-acf6ebe74b1f":{"quantity":1,"FirstName":"Matthew", "LastName":"Smith"}
}
const productId = "92ef2918-6bc2-4f3b-b9b3-acf6ebe74b1f";
const firstName = "Matthew";
const lastName = "Smith";
const quantity = 1;
const cartItem = cart[productId];
if(typeof cartItem !== "undefined" && cartItem.FirstName === firstName && cartItem.LastName === lastName && cartItem.quantity >= 1) {
cartItem.quantity += 1;
};
console.log(cart);
Once you have a handle on the intended cart property, you can simply increment its quantity property.
If you need deep equality based on enumerable properties only (that is: the values that you get when you use for...of, or Object.keys, etc.) then you can determine equality based on the JSON serialization of those objects, provided you force key sorting, using the rarely talked about replacer argument for JSON.stringify().
This is an incredibly powerful feature of the JSON serialization process, and we can write a simple function that will guarantee any object we pass in will always serialize to the same JSON string, regardless of key ordering at any depth:
function sortedObjectKeys(_, data) {
// Ignore primitives.
if (data === null) return null;
if (typeof data !== "object") return data;
// Also ignore iterables, which are type "object" but
// should not be sorted because [1,2,3] is not [1,3,2].
if (data.__proto__[Symbol.iterator]) return data;
// Then sort the object keys and yield a new object with that
// ordering enforced by key insertion.
return Object.fromEntries(Object.entries(data).sort());
}
We can now perform a deep equality test using string equality:
function deepEqual(o1, o2) {
const s1 = JSON.stringify(o1, sortedObjectKeys);
const s2 = JSON.stringify(o2, sortedObjectKeys);
return s1 === s2;
}
let cart = {
"98eb9514-f403-4d08-b5f7-dd6a5ec013cb": {
"quantity": 1,
"FirstName": "John",
"LastName": "Lewis"
},
"92ef2918-6bc2-4f3b-b9b3-acf6ebe74b1f": {
"quantity": 1,
"FirstName": "Matthew",
"LastName": "Smith"
}
}
let productId = '98eb9514-f403-4d08-b5f7-dd6a5ec013cb'; // any product key
let valueToMAtch = 1; // any value to match
let productKey = Object.keys(cart).find((key) => key === productId);
Object.entries(cart[productKey] || {}).forEach(([key, value]) => { // || {} allows undefined handing if no product is found
if (value === valueToMAtch) {
cart[productKey][key] += 1; // adding one
}
});
console.log(cart); // result