Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A better vanilla JS approach to finding any false value in a nested object?

Tags:

javascript

If I have an object, such as:

const obj = {
  field1: {
    subfield1: true,
    subfield2: true,
  },
  field2: {
    subfield3: true,
  },
  field3: {
    subfield4: false,
    subfield5: true,
  }
}

Then I can do a nested for loop to return true if a value is false by doing,

const findFalse = obj => {
  for (const field in obj) {
    for (const subfield in obj[field]) {
      if (!obj[field][subfield]) return true
    }
  }
}

If this object wasn't nested, it'd be a bit easier, I could do something like,

const findFalse = obj => Object.keys(obj).some(prop => !obj[prop]);

Both approaches don't really suit what I need, because the object can have 2, 3 or more nested properties. I've come up with a recursive way to figure this out, such as:

const isObj = obj => obj && obj.constructor === Object;

const findFalseRecursively = obj => {
  for (const field in obj) {
    if (isObj(obj[field]))
      return findFalseRecursively(obj[field])

    if (obj[field] === false)
      return true
  }
}

But I'm wondering if there's a cleaner or more efficient way of achieving this?

I would expect the function to return the first false value that it sees, and break out of the function/for loop instantly.

like image 581
Mike K Avatar asked Jul 22 '20 09:07

Mike K


People also ask

Which among these is are the correct way of accessing values of nested objects?

A nested data structure is an array or object which refers to other arrays or objects, i.e. its values are arrays or objects. Such structures can be accessed by consecutively applying dot or bracket notation.

What is vanilla JavaScript used for?

Vanilla JavaScript refers to using plain Javascript without any additional libraries or frameworks. The term became popular when Eric Wastl created the Vanilla JS site in 2012 as a joke. The site tries to bring attention to the fact that you can use just plain Javascript in many cases.

How do I create a nested object in JavaScript?

Creating Nested Objects in JavaScript Dynamically In ES6, Objects can be created with computed properties. To use a “dynamic” key, you have to use bracket notation: Iterate through the elements of basis . Use the keys to find the corresponding element in nested , and use that as the key in the new object being created.

How do I update nested objects?

To update nested properties in a state object in React: Pass a function to setState to get access to the current state object. Use the spread syntax (...) to create a shallow copy of the object and the nested properties. Override the properties you need to update.


2 Answers

You could take the valus from the object and iterate with a short circuit.

const 
    hasTrue = object => Object
        .values(object)
        .some(v => v === false || v && typeof v === 'object' && hasTrue(v)),
    object = { field1: { subfield1: true, subfield2: true }, field2: { subfield3: true }, field3: { subfield4: false, subfield5: true } };

console.log(hasTrue(object));

With suggested check object in advance

const 
    hasTrue = value => value === true || !!value && typeof value === 'object' && Object
        .values(value)
        .some(hasTrue),
    object = { field1: { subfield1: true, subfield2: true }, field2: { subfield3: true }, field3: { subfield4: false, subfield5: true } };

console.log(hasTrue(object));
like image 145
Nina Scholz Avatar answered Oct 19 '22 17:10

Nina Scholz


Here is a simple recursive solution that uses Object.values,flat and some.

function toValues (obj) {
    if (typeof obj === 'object') return Object.values(obj).map(toValues);
    return obj;
}
const findFalse = obj => toValues(obj).flat().some(v => v === false)

const res = findFalse(obj);

console.log (res);
<script>
const obj = {
  field1: {
    subfield1: true,
    subfield2: true,
  },
  field2: {
    subfield3: true,
  },
  field3: {
    subfield4: false,
    subfield5: true,
  }
}
</script>
like image 42
Moritz Roessler Avatar answered Oct 19 '22 18:10

Moritz Roessler