4

I wanted to find out if my object is empty or not for all its nested objects and key-value pairs.

for e.g.,

const x = {
  a:"",
  b:[],
  c:{
    x:[]
  },
  d:{
    x:{
      y:{
        z:""
      }
    }
  }
};

this should be an empty object and if any of this contains single value then it should be non empty.

Jaydeep Galani
  • 4,842
  • 3
  • 27
  • 47

4 Answers4

6

Here is the way to do what using recursion

const x = {
  a:"",
  b:[],
  c:{
    x:[]
  },
  d:{
    x:{
      y:{
        z:''
      }
    }
  }
};
function checkEmpty(obj){
  
  for(let key in obj){
    //if the value is 'object'
    if(obj[key] instanceof Object === true){
      if(checkEmpty(obj[key]) === false) return false;
    }
    //if value is string/number
    else{
      //if array or string have length is not 0.
      if(obj[key].length !== 0) return false;
    }
  }
  return true;
}
console.log(checkEmpty(x))
x.d.x.y.z = 0;
console.log(checkEmpty(x));
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
1

You can write a recursive function like following. Function creates a set with 2 possible values true and false. If the size of set is 1 and the value being false, which mean that the object is empty.

const x = {a:"",b:[],c:{x:[]},d:{x:{y:{z:""}}}};

function isEmpty(o, r = new Set()) {
  for (let k in o) {
    if(typeof o[k] === "object") {
      if(Array.isArray(o[k])) r.add(!!o[k].length);
      else isEmpty(o[k],r);
    } else r.add(!(o[k] === "" || o[k] === undefined || o[k] === null));
  }
  return r;
}
let result = isEmpty(x);

console.log(result.has(false) && result.size == 1);
Nikhil Aggarwal
  • 28,197
  • 4
  • 43
  • 59
1

I will use a recursive approach for this one, we iterate over the object.keys() and check is every value related to the key is empty, in the case the value is an object, we go one level deeper to check it.

const x = {
  a:"",
  b:[],
  c:{x:[]},
  d:{x:{y:{z:""}}}
};

const x1 = [0,0,0];
const x2 = {0:0,1:0,2:0};

const isEmpty = (obj, empty=true) =>
{
    Object.keys(obj).forEach((key) =>
    {
        if (typeof obj[key] === "object")
            empty = isEmpty(obj[key], empty);
        else
            empty = empty && (obj[key].length === 0);
            
        // Return early if we detect empty here.
        
        if (!empty) return empty;
    });
    
    return empty;
}

console.log("original x: ", isEmpty(x));

x.a = "I'm not empty";

console.log("x after edit: ", isEmpty(x));
console.log("x1: ", isEmpty(x1));
console.log("x2: ", isEmpty(x2));
Shidersz
  • 16,846
  • 2
  • 23
  • 48
  • You code will return `true` even if there will a value `0` – Maheer Ali Feb 12 '19 at 05:18
  • @MaheerAli I really don't understand well what he consider empty, in his example this `{z:""}` is considered empty. For me that is not empty. If he clarify with other cases I will update the answer, however the approach will be similar. Could you give me an example where my code fails, so I can analize it... – Shidersz Feb 12 '19 at 05:30
  • use `x.a = 0;` and then check it will return `true` – Maheer Ali Feb 12 '19 at 05:38
  • For example, will this be an empty object `[0,0,0]` or not? If no, then `{0:0, 1:0, 2:0}` should not be considered empty also. – Shidersz Feb 12 '19 at 05:39
  • 1
    neither `[0,0,0]` should be considered empty not `{0:0, 1:0, 2:0}`. In his question he showed only `[]` and `''` – Maheer Ali Feb 12 '19 at 05:41
1

try (we use here recursion, fat arrow, obj. keys, reduce, ternary operator and object checking)

let isEmpty = o => o.constructor.name === "Object" ? 
  Object.keys(o).reduce((y,z)=> y&&isEmpty(o[z]) ,true) : o.length == 0;

const x = {
  a:"",
  b:[],
  c:{
    x:[]
  },
  d:{
    x:{
      y:{
        z:""
      }
    }
  }
};


let isEmpty = o => o.constructor.name === "Object" ? 
    Object.keys(o).reduce((y,z)=> y&&isEmpty(o[z]) ,true) : o.length == 0;
  


// Test
console.log(isEmpty(x));
x.d.x.y.z="Smile to life and life will smile to you";
console.log(isEmpty(x));
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345