-
-
Save JoshDevHub/b00125f483d4a1ecc257eaa030916973 to your computer and use it in GitHub Desktop.
// solution to problem #6 in recursive exercises | |
function contains(object, searchValue) { | |
// because `null` has a typof "object", we have to explicitly check | |
// to prevent trying to access `null`'s values (which don't exist) | |
if (typeof object !== "object" || object === null) { | |
return object === searchValue; | |
} | |
for (const value of Object.values(object)) { | |
// An important problem in the code quiz solution is that `return contains()` will only | |
// search the first property of an object, as it will return whatever the result for it is. | |
// If our value was nested within the second property, for example, it would never get checked | |
// even if the first nested object did not contain it. | |
if (contains(value, searchValue)) { | |
return true; | |
} | |
} | |
return false; | |
} |
I thought I needed to search for the keys and values:
function contains(obj, item) {
if (Object.values(obj).length === 0) return false;
else if (item in obj || Object.values(obj).includes(item)) return true;
else {
for (let value of Object.values(obj)) {
return contains(value, item);
}
}
}
Here is a more improved answer that even runs for flat objects as well as nested ones.
The provided first code doesn't check directly the equality of the value; it directly jump to nested, leaving the flat object unchecked
here is the improved code
function contains(object, searchValue) {
if (typeof object !== "object" || object === null) {
return object === searchValue;
}
for (const value of Object.values(object)) {
// First check direct equality
if (value === searchValue) {
return true;
}
// Then check nested objects
if (typeof value === "object" && value !== null) {
if (contains(value, searchValue)) {
return true;
}
}
}
return false;
}
OR
function contains(object, searchValue) {
// Handle non-objects
if (typeof object !== "object" || object === null) {
return object === searchValue;
}
// Check all values
for (const value of Object.values(object)) {
// Direct match OR recursive match
if (value === searchValue || contains(value, searchValue)) {
return true;
}
}
return false;
}
Unless I'm missing something, the given solution in the original post works with flat objects just fine @kazeneza-zephilin
Your solution is also more repetitive, effectively adding the exact same guard check twice. This might have some marginal performance gains by avoiding new stack frames in certain contexts, but I think it's unlikely to be meaningful.
Came up with this function myself:
Felt quite good about it even though I knew that a
null
could very easily render it useless. But then I realised that I could just change the third line to:if (typeof currentVal === "object" && currentVal !== null) {
to prevent that from happening.