How to check if every properties in an object are null - javascript

I have an object, sometimes it is empty like so {} other times it will have properties that are set to null.
{
property1: null,
property2: null
}
How can I determine if ALL the properties within this object is null?
If they are all null then return false.
At the moment I'm using lodash to check for the first case where the object is simply {} empty. But I also need to cover the second case.
if (isEmpty(this.report.device)) {
return false;
}
return true;

You can use Object.values to convert the object into array and use every to check each element. Use ! to negate the value.
let report = {
property1: null,
property2: null,
}
let result = !Object.values(report).every(o => o === null);
console.log(result);
An example some elements are not null
let report = {
property1: null,
property2: 1,
}
let result = !Object.values(report).every(o => o === null);
console.log(result);
Doc: Object.values(), every()

Approach using .some() instead of .every():
function isEmpty (obj) {
return !Object.values(obj).some(element => element !== null);
}
This function (named isEmpty to match the name given in the question) shall return false if any obj property is not null and true otherwise.

You can use the Object.keys() method this will return all keys in that Object as an Array. This makes it possible to do Object.keys(this.report.device).filter(key => !this.report.device[key] === null), which will return you the amount of not null keys, if this is 0 then you have your answer.
In essence relying on null properties is not such a good approach it's better to make those properties undefined or just to return a flat Object from your API.
Hope this helped.

This is very simple and can be done with a one liner !
function IsAllPropertiesNull(obj) {
return Object.values(obj).every(v=>v == null);
}
a = {'a': null, 'b':null};
var isAllNull = IsAllPropertiesNull(a)
// isAllNull = true
explanation -
get all values of object - iterate them and check for null
Good luck!

Use Object.entries and Array.every
let obj = {
property1: null,
property2: null,
};
function isEmpty(o) {
return Object.entries(o).every(([k,v]) => v === null);
}
if(isEmpty(obj)) {
console.log("Object is empty");
}

In order to check if object has null value for all the keys. One cleaner approach could be.
const set = new Set(Object.values(obj));
const hasOnlyNullValues = set.size === 1 && set.has(null);

For Es2015
if (Object.keys(obj).map(e => obj[e]).every(a => a.length === 0)) {
console.log('all are empty');
}

Related

Checking 'undefined' or 'null' of any Object

I am working on Angular project and time to time I used to have check undefined or null over Object or it's properties. Normally I use lodash _.isUndefined() see example below:
this.selectedItem.filter(i => {
if(_.isUndefined(i.id)) {
this.selectedItem.pop();
}
})
I couldn't see any problem with it. But I had discussion with my colleague during review of above code. He was telling me that if i gets undefined before the if statement then it will throw the exception. Instead he suggested me to always check i or i.id like this:
if(!!i && !!i.id) {
this.selectedItem.pop();
}
I am convinced what he was trying to say unlike his way of checking undefined in above code. But then I was thinking what is the purpose of lodash _.isUndefined?
Could anyone please let me know what is the best or clean way to do it. Because for me !!i && !!i.id is not readable at all.
Many thanks in advance.
You can use _.isNil() to detect undefined or null. Since you're using Array.filter(), you want to return the results of !_.isNil(). Since i is supposed to be an object, you can use !_.isNil(i && i.id).
Note: you are using Array.filter() as Array.forEach(). The callback of Array.filter() should return a boolean, and the result of the filter is a new array.
const selectedItem = [
undefined,
{},
{ id: 5 },
undefined,
{ id: 7 },
];
const result = selectedItem.filter(i => !_.isNil(i?.id));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
You can also use _.reject() and save the need to add !:
const selectedItem = [
undefined,
{},
{ id: 5 },
undefined,
{ id: 7 },
];
const result = _.reject(selectedItem, i => _.isNil(i?.id));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Use typeof i.id === 'undefined' to check for undefined and i.id === null to check for null.
You could write your own helper functions to wrap any logic like what LoDash has. The condition with !!i && !!i.id is only looking for falsy values (empty string, 0, etc), not only null or undefined.
You could check for i and if it is not truthy or if the property is undefined or null, then do something.
if (!i || i.id === undefined || i.id === null) {
this.selectedItem.pop();
}
Referring to a variable which has undefined as it's value won't throw any error. You get a ReferenceError for referring to variable that is not defined:
> i
Uncaught ReferenceError: i is not defined
If you pass a not-defined variable to a function a ReferenceError is thrown and the function won't be executed.
> _.isUndefined(i)
Uncaught ReferenceError: i is not defined
typeof operator should be used for safely checking whether a variable is defined or not:
> typeof i
'undefined'
In your code the i is defined (it's a function argument) so by referring to it you won't get any ReferenceError. The code will throw a TypeError when i is defined, has undefined value and you are treating it as an object:
> var i = undefined; i.id
Uncaught TypeError: Cannot read property 'id' of undefined
let words = [null, undefined, 'cheaters', 'pan', 'ear', 'era']
console.log(words.filter(word => word != null));
Your friend is right. When you do, _.isUndefined(i.id) you're assuming i to not to be undefined. You're assuming i is an object which will have an id property which you're checking if it is falsey or not.
What happens when the variable i itself is undefined? So you will end up undefined.id which is an error. Therefore you could simply do this
if(i && i.id) {
// You're good to go
}
The above will check for all falsey values, 0 and "" included. So if you want to be very specific, then you'll have to check the types of both using typeof operator.
May I suggest checking for if(typeof(element) == "number" && element) {} In this case the typeof() part catches any non numbers and the element part should catch any NaNs (typeof(NaN) returns "number")
You can use lodash#get (it will handle if the root is value null or undefined), and then compare the output with null using == or !=, instead of using === or !==. if the output is null or undefined then comparing with == will be true and != will be false.
const selectedItem = [
undefined,
{},
{id: null},
{ id: 5 },
undefined,
{ id: 0 },
{ id: 7 },
];
const res = selectedItem.filter(a => _.get(a, 'id') != null);
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
using lodash#get you can checkfor any nested level for its existence with out subsequent && like a && a.b && a.b.c && a.b.c.d (in case of d) look at this answer of mine for nested level checking with lodash#get
Also you can use _.isNill instead of comparing with null will == or !=
Another more "lodashy" approach would be to use _.conforms. The readability is much better in my opinion and you get access directly to id so no problems with undefined before that:
const items = [
undefined,
{ id: null},
{ id: 5 },
{ id: "4" },
{ id: undefined },
undefined,
{ id: 0 },
{ id: 7 },
{ id: () => 3 }
];
const numbersOnly = _.filter(items, _.conforms({'id': _.isNumber}));
console.log('numbers', numbersOnly);
const allDefined = _.filter(items, _.conforms({'id': _.negate(_.isUndefined)}));
console.log('defined', allDefined);
const stringsOnly = _.filter(items, _.conforms({'id': _.isString}));
console.log('strings', stringsOnly);
const functionsOnly = _.filter(items, _.conforms({'id': _.isFunction}));
console.log('functions', functionsOnly);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Javascript has now (Chrome 80, Safari 13.4) Optional chaining (?.)
The optional chaining operator (?.) permits reading the value of a
property located deep within a chain of connected objects without
having to expressly validate that each reference in the chain is
valid.
This means you could check for id without causing an exception in case i is undefined
this.selectedItem.filter(i => {
if(i?.id) {
this.selectedItem.pop();
}
})
Or since you are using filter, you can check test this live on the filter documentation.
const words = ['spray', undefined, 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word?.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
Additionally, also worth to mention, as #Koushik Chatterjee's answer points, lodash _.get allows you to describe a path to a deep property safely, and even give a default value in case it doesn't exist.
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.get(object, ['a', '0', 'b', 'c']);
// => 3
_.get(object, 'a.b.c', 'default');
// => 'default'

Using jQuery grep on an object

I have an object which looks like that:
const myObject = {
3723723: null
,3434355: true
,9202002: null
}
Using jQuery grep method I need to get the count of the array where the value is not null.
const result = $.grep(myArray, function (k, v) { return v != null; });
const count = result.length;
The variable you're talking about is actually not an array, but an object.
You don't need jQuery to find the number of values which are not null. Call the Object.values() function to get the values of that object as an array, then use the filter() method to filter out values which are null and then check the length property.
const myObject = {
3723723: null
,3434355: true
,9202002: null
}
console.log(Object.values(myObject).filter(x => x !== null).length)
Alternative solution using Object.keys():
const myObject = {
3723723: null
,3434355: true
,9202002: null
}
console.log(Object.keys(myObject)
.map(x => myObject[x])
.filter(x => x !== null).length)
In JavaScript you can use objects to get data structure you want.
var data = {
3723723: null,
3434355: true,
9202002: null
}
And to count properties where the value isn't null you can use Object.keys() to get array of object keys and then reduce() to get count.
var data = {
3723723: null,
3434355: true,
9202002: null
}
var result = Object.keys(data).reduce(function(r, e) {
if(data[e] != null) r += 1;
return r;
}, 0);
console.log(result)

Look through an array of objects and remove undefined from its property

I have an array of objects, I would like to remove 'undefined' from any of the properties in any of the objects.
To remove undefined from an object, I use this method,
removeNullorUndefined:function(model) {
function recursiveFix(o) {
// loop through each property in the provided value
for (var k in o) {
// make sure the value owns the key
if (o.hasOwnProperty(k)) {
if (o[k] === 'undefined') {
// if the value is undefined, set it to 'null'
o[k] = '';
} else if (typeof (o[k]) !== 'string' && o[k].length > 0) {
// if there are sub-keys, make a recursive call
recursiveFix(o[k]);
}
}
}
}
var cloned = $.extend(true, {}, model);
recursiveFix(cloned);
return cloned;
},
How can I modify this so it can also accept an array of objects and remove 'undefined' from it ?
Appreciate any inputs
As long as the value is undefined and not a string value of 'undefined' then one way is to use JSON.stringify. Referring to property values:
If undefined, a function, or a symbol is encountered during conversion it is either omitted (when it is found in an object) or censored to null (when it is found in an array). JSON.stringify can also just return undefined when passing in "pure" values like JSON.stringify(function(){}) or JSON.stringify(undefined).
So, you could stringify an object and immediately parse it to remove undefined values.
NOTE: This approach will deep clone the entire object. In other words if references need to be maintained this approach won't work.
var obj = {
foo: undefined,
bar: ''
};
var cleanObj = JSON.parse(JSON.stringify(obj));
// For dispaly purposes only
document.write(JSON.stringify(cleanObj, null, 2));
An added bonus is without any special logic it will work at any depth:
var obj = {
foo: {
far: true,
boo: undefined
},
bar: ''
};
var cleanObj = JSON.parse(JSON.stringify(obj));
// For dispaly purposes only
document.write(JSON.stringify(cleanObj, null, 2));
If it is a string value of 'undefined' you can use the same approach but with a replacer function:
var obj = {
foo: {
far: true,
boo: 'undefined'
},
bar: ''
};
var cleanObj = JSON.parse(JSON.stringify(obj, replacer));
function replacer(key, value) {
if (typeof value === 'string' && value === 'undefined') {
return undefined;
}
return value;
}
// For dispaly purposes only
document.write(JSON.stringify(cleanObj, null, 2));
If you like the way removeNullorUndefined() currently works then you might try:
items.forEach(function(item){ removeNullorUndefined(item); });

lodash: check object is empty

I have this object:
{"": undefined}
and when I check this object for empty in this way:
_.isEmpty({"": undefined})
I get false result, maybe in lodash we have another method?
_.isEmpty(obj, true)
var obj = {
'firstName': undefined
, 'lastName' : undefined
};
console.log(_.isEmpty(obj)); // false
console.log(_.isEmpty({})); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Please, see http://www.ericfeminella.com/blog/2012/08/18/determining-if-an-object-is-empty-with-underscore-lo-dash/
Your example object is not empty so instead perhaps you want to test if all properties are undefined
let o = {foo: undefined};
!_.values(o).some(x => x !== undefined); // true
It depends on how you want to check it.
Do you want to check some or every
Then what you can do is :
import { some, isEmpty } from 'lodash'
console.log(some(this.yourObject, isEmpty))
In your case it cannot be called an empty object (Object.values(obj).length would return 1), but for a completely empty object this can be used:
import { matches } from 'lodash';
matches(obj, {});
I guess this is a bit overkill, but this is what I use which recursively checks for nested objects too and uses lodash.
function checkEmptyObject(obj) {
if (_.isEmpty(obj)) return true;
return _.isEmpty(
Object.entries(obj)
.map(([key, value]) => {
if (_.isEmpty(value)) return true;
if (value instanceof Object) return checkEmptyObject(value);
return false;
})
.filter((b) => b === false)
);
}
I'd do it this way
_.isEmpty(_.omitBy(object_to_check, _.isNil)
_.omitBy removes all the keys with null & undefined values in this example.
To remove only undefined you can use _.isUndefined instead of _.isNil
To provide an alternative to Lodash - this is how I do the same with vanilla JS ES6.
const isEmpty = (obj) => {
return obj === undefined ? true : Object.keys(obj).length === 0
}
console.log(isEmpty(undefined))
console.log(isEmpty({}))

Javascript if a value exists in an object?

ive got an object:
var car = {
company: "Honda",
year: "2011",
Model: "Brio"
}
I was wondering if there exists an inherited method (is that the right phrase?) to check if a value exists inside a given object, somewhat like x.hasOwnProperty, or if (x in car). Or, should I write my own.
I've done a few google searches, but they all either lead to hasOwnProperty or to check if a value exists inside an array.
Editing to please all the people in the comments:
There are two use cases i could think of where this would be useful:
checking for undefined keys and reporting which one
if (!car.isInvalid(car, undefined))
validCarsArray.push (car);
Checking if a general user input exists in an object
var text = searchBox.input;
validCarArrays.forEach (function (car) {
if (car.hasOwnValue(car, text)) {
displayToUserAsResult (car);
}
});
Let's say we start with
const obj = {foo : "bar"};
Check for a value:
const hasValue = Object.values(obj).includes("bar");
Check for a property:
// NOTE: Requires obj.toString() if key is a number
const hasProperty = Object.keys(obj).includes("foo");
Multi-level value:
function hasValueDeep(json, findValue) {
const values = Object.values(json);
let hasValue = values.includes(findValue);
values.forEach(function(value) {
if (typeof value === "object") {
hasValue = hasValue || hasValueDeep(value, findValue);
}
})
return hasValue;
}
Multi-level property:
function hasPropertyDeep(json, findProperty) {
const keys = Object.keys(json);
let hasProperty = keys.includes((findProperty).toString());
keys.forEach(function(key) {
const value = json[key];
if (typeof value === "object") {
hasProperty = hasProperty || hasPropertyDeep(value, findProperty);
}
})
return hasProperty;
}
No, there is no built in method to search for a value on an object.
The only way to do so is to iterate over all the keys of the object and check each value. Using techniques that would work even in old browsers, you can do this:
function findValue(o, value) {
for (var prop in o) {
if (o.hasOwnProperty(prop) && o[prop] === value) {
return prop;
}
}
return null;
}
findValue(car, "2011"); // will return "year"
findValue(car, "2012"); // will return null
Note: This will return the first property that contains the search value even though there could be more than one property that matched. At the cost of efficiency, you could return an array of all properties that contain the desired value.
Note: This uses the extra .hasOwnProperty() check as a safeguard against any code that adds enumerable properties to Object.prototype. If there is no such code and you're sure there never will be, then the .hasOwnProperty() check can be eliminated.
There is no built-in function but it can be done using Object.keys() and [].some():
function hasValue(obj, value) {
return Object.keys(obj).some((key) => obj[key] == value);
}
var car = {
company: "Honda",
year: "2011",
Model: "Brio"
}
snippet.log('car has Honda: ' + hasValue(car, 'Honda'));
snippet.log('car has NotHonda: ' + hasValue(car, 'NotHonda'));
<script src="https://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
This function uses Object.keys() and returns an array with the keys for the object which has the given value.
The Object.keys() method returns an array of a given object's own enumerable properties, in the same order as that provided by a for ... in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
var car = {
company: "Honda",
year: "2011",
Model: "Brio"
};
function getKeysWithValue(v, o) {
return Object.keys(o).filter(function (k) {
return o[k] === v;
});
}
document.write('<pre>' + JSON.stringify(getKeysWithValue('Honda', car), 0, 4) + '</pre>');
I used this function, to check wether or not array2 contains a common value with array1.
const array1 = ['a','b','c','x'];
const array2 = ['z','y','x'];
function ContainsCommonItem3(arr1, arr2){
return arr1.some(item => arr2.includes(item));
}

Categories