How to check if an object is "deep empty"? - javascript

i have a method that returns an object that contains 4 objects:
function getFiles() {
var documents = {};
documents.files1ToBeCompleted = DocumentsService.getFiles1Uncompleted();
documents.files2ToBeCompleted = DocumentsService.getFiles2Uncompleted();
documents.files3ToBeCompleted = DocumentsService.getFiles3Uncompleted();
documents.files4ToBeCompleted = DocumentsService.getFiles4Uncompleted();
return documents;
}
I'm trying to use Underscore function ._isEmpty to verify if the object is empty, i mean the case in which i get an object with empty sub-objects.
But even all its 4 objects are empty, it is not empty because it contains 4 items.
Do you know any way to check if an object is "deep empty"?

Here's what worked for me. It is recursive and takes care of all nested objects (uses lodash).
function isEmptyDeep(obj) {
if(isObject(obj)) {
if(Object.keys(obj).length === 0) return true
return every(map(obj, v => isEmptyDeep(v)))
} else if(isString(obj)) {
return !obj.length
}
return false
}
It first checks if there are no keys, and returns true in that case.
Then it checks the keys and runs isEmptyDeep on each. If the value is an object (or array), it will continue recursion.
If there's an empty array or empty string, length will be 0 and will be considered empty.
If the value is 0, false, or other falsy values, then it would be considered not empty. If you want to consider falsey values as empty, this as the first line in the function above:
if(!obj) return true

Thanks to Bergi that lead me to this working solution:
_.every(documentsObject, function(property) { return _.isEmpty(property); });
that returns true if the object is "deep empty", false otherwise.

Related

"Infinity" if I don't pass any number as parameters

Having this issue most likely I am doing everything wrong, but I wanted to find the smallest and the biggest number inside an array and return it to a new object, and if this array is empty I wanted to have a simple empty object. This is the logic I have used
function findBiggestAndSmallest(numbers) {
const biggest = Math.max(...numbers);
const smallest = Math.min(...numbers);
if (numbers === []) {
return {};
}
return { biggest, smallest };
}
console.log(findBiggestAndSmallest([]));
console.log(findBiggestAndSmallest([2,1,5,100,20]));
and it's working fine as long I put numbers inside the array but when I leave an empty array the result is -infinity and Infinity, even though I specified that if the parameter is an empty array just return an empty object.
Thank you for your support.
The if statement "if(numbers === [])" is a comparison of arrays, which are a special type of objects. Objects are stored with their references so you cannot compare the content equality of arrays in this manner because the comparison will check if the two objects are pointing towards the exact same place in memory.
// This will ALWAYS return false
console.log([]===[])
function findBiggestAndSmallest(numbers) {
// Always do error handling first :)
if (!numbers.length) {
return {}
}
const biggest = Math.max(...numbers)
const smallest = Math.min(...numbers)
return { biggest, smallest }
}
// Now returns empty object, maybe consider just returning false
console.log(findBiggestAndSmallest([]))
// Example
console.log(findBiggestAndSmallest([2,1,5,100,20]))

How to check whether an object is empty? [duplicate]

This question already has answers here:
How do I test for an empty JavaScript object?
(48 answers)
Closed 7 months ago.
I'm learing JavaScript. I cannot grasp the idea of an empty object. As I understand, there are situations when I need to check a variable whether it holds an object and has a value.
So far, I know that a variable can be undefined.
var car; // the value is undefined, as well as the type (which is it? number, array, etc.)
I also know, that everything that has a value, is true:
var car = "Opel";
Boolean(car); // true
And anything without a value is false:
var car = ""; // typeof string, but it is empty, so
Boolean(car); // false
Boolean(null); // false
So why doesn't it work the same way with arrays and objects? Why is all of this true? Shouldn't empty arrays and objects return false?
var car = {make: "Opel", year: 2015};
Boolean(car); // true
car = {};
Boolean(car); // true
car = ["BMW", "Opel"];
Boolean(car); // true
car = [];
Boolean(car); // true
Now I see that there are methods, that can be applied to check an object's length, I just haven't reached that part yet.
I'm learning at W3Schools website and this bit just got me puzzled:
But you cannot test if an object is null, because this will throw an error if the object is undefined:
Incorrect:
if (myObj === null)
To solve this problem, you must test if an object is not null, and not undefined.
But this can still throw an error:
Incorrect:
if (myObj !== null && typeof myObj !== "undefined")
Because of this, you must test for not undefined before you can test for not null:
Correct:
if (typeof myObj !== "undefined" && myObj !== null)
I still cannot understand the last line here.
Checking if an object is empty:
Object.keys(yourObject).length
var car = {};
var isEmpty = Object.entries(car).length > 0; //false
var car = {make: "Opel", year: 2015};
var isEmpty = Object.entries(car).length > 0; //true
This should solve your problem, if your curious about the utility function Object.entries you can look on mdn
I also know, that everything that has a value, is true
I wouldn't say that. All the examples given are values, even undefined and null are predefined values in JavaScript.
Shouldn't empty arrays and objects return false?
It is like that by specification. And that is really the answer to your question. It is a choice made by the designers of the language.
You could find some logic in it though. In JavaScript, values representing objects (and so also arrays) are references. These references are memory addresses/pointers, and although you cannot find out what exactly those addresses are, these are non-zero, even when an object has no properties.
Note that your example objects ({} and []) still have some non-enumerable properties, such a __proto__ and (for array) length, so they are not really as empty as you think.
The most empty object you can create, is: Object.create(null)
You can check wheather a object is empty or not in this simple way.
function objectLength( object ) {
return Object.keys(object).length;
}
if(objectLength(yourObject) == 0){
//object is empty
}else{
//object not empty
}
Checking if an object is empty:
Reflect.ownKeys(car).length
Returns an array with one element when a Symbol is used as the key:
let key = Symbol('vin')
let car = { [key]: 'honda' }
Reflect.ownKeys(car).length // => 1
Whereas Object.keys returns an array with zero elements in this case:
let key = Symbol('vin')
let car = { [key]: 'honda' }
Object.keys(car).length // => 0
I would always use typeof myvar !== 'undefined' and checks for content myvar !== ''
This would always would have a clear result.
There are concepts which are Truthy and Falsy values in JavaScript.
I highly recommend you to read MDN documents about this issue.
All values are truthy unless they are defined as falsy (i.e., except for false, 0, -0, 0n, "", null, undefined, and NaN).
Truthy values
Falsy values
No, they should not be false.
All objects are 'truthy', in that they return true when evaluated as a Boolean. In Javascript, all arrays are objects (try console.log(typeof [])), so they also return true, regardless of whether or not they are empty.
To check if any array is empty:
if (MYARRAY.length === 0) {
// console.log(true);
}
To check if an object is empty:
if (Object.keys(MYOBJECT).length === 0) {
// console.log(true);
}
You can use
if ($('#element').is(':empty')){
//do something
}
OR
function isEmpty( el ){
return !$.trim(el.html())
}
if (isEmpty($('#element'))) {
// do something
}
Here are some examples: http://api.jquery.com/is/
But if you need it in JavaScript:
if( typeof foo !== 'undefined' ) {
// foo could get resolved and it's defined
}
You can simply use typeof

How to use 'in' keyword in Javascript

I have a question here. I know my code have plenty of problems and I need your help.
The problem is, To return an object which have numbers of repetition information of the string.
The given string is
var r = countFreq(["a", "b", "b", "c", "c", "c", "d"]);
and the result have to be
{"a":1, "b":2, "c":3, "d":1 }
by console.log(r);
All that I know is, key(properties) have to be element and value(value of property) have to be the number of repetition.
AND, I must use 'in' key world to solve this problem.
Like,
if('property' in 'object') {
//...
}else {
//...
}
(if there's no property initialize as 1, and if there's a same property, add 1 each time)
I really appreciate your help.
(This post may have grammatical errors. I really feel sorry about that...)
function countFreq(array) {
var i;
for(i=0; i<array.length; i++)
{
if(array[i] in array)
{
return i += 1;
}else
{
return i = 1;
}
console.log(array[i]+": "+i+", ");
}
}
var r = countFreq(["a","b","c","c","c","d"]);
console.log(r);
According to MDN - The 'in' operator returns true if the specified property is in the specified object or its prototype chain.
Prop is a string or symbol representing a property name or array index (non-symbols will be coerced to strings).
Object is to check if it (or its prototype chain) contains the property with specified name.
So in your case, it depends what your object is? if you object is an array, you need to use prop as properties of array. All index values up to length of array will return true.
MDN Example of arrays
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
0 in trees // returns true
3 in trees // returns true
6 in trees // returns false
'bay' in trees // returns false (you must specify the
// index number, not the value at that index)
'length' in trees // returns true (length is an Array property)
Symbol.iterator in trees // returns true (arrays are iterable, works only in ES2015+)
I think you are misunderstanding the in operator. In can be used in 2 cases, as a boolean operator to check for the presence of an index in an array or to iterate over the indexes of an array with a for loop. You are using it to check for the presence of a value in an array directly, which you cannot do. Also you are returning from the function after each iteration so you will only ever get 1 or 0.
I presume you want something like the following:
countFreq(array) {
var results = { a: 0, b: 0, c: 0, d: 0 };
for (var index in array) {
results[array[index]] ++;
}
return results;
}
Now you can access each result with results[‘a’] for instance, after calling countFreq. I think you need to read up on return and loops in JavaScript.

Why does my function require two return statements for it to be correct?

So my coding exercise has me create a function “getElementsGreaterThan10AtProperty” that returns an array containing the elements within the array, located at the given key, that are greater than 10. Playing around with the code I cant figure out why my filter method requires two return statements. Any tips to help me understand would be very appreciated.
function getElementsGreaterThan10AtProperty(obj, key) {
if (!Array.isArray(obj[key]) || obj[key].length < 1 ) {
return [];
} else {
return obj[key].filter(function(item){
return item > 10;
});
}
}
Also,
If the array is empty, it should return an empty array.
If the array contains no elements greater than 10, it should return an empty array.
If the property at the given key is not an array, it should return an empty array.
If there is no property at the key, it should return an empty array
The Array.prototype.filter function returns a new Array using a filter function.
The callback filter function must return a Boolean indicating whether or not an item is kept. So...
// the outer `return` returns the resulting Array.
return obj[key].filter(function(item){
// The inner `return` returns a pass/fail (true/false)
return item > 10;
});

Object get the value by a key

I'm kinda stuck with an issue. This is the response for my AJAX call.
var test = [
{
"analytics.feature": "false"
},
{
"demo": "true"
},
{
"analytics.demo": "false"
}
]
Now I want to check if analytics.demo is enabled or disabled.
Can I use _.find?
_.find(test, {analytics.demo}); //returns error
I just want to do this
if(analytics.demo) {
//Do something
}
How do I do that? Can someone help?
Instead of iterating objects and comparing, can I use underscorejs/jQuery to get the exact value for a key?
const options = Object.assign(...test)
console.log(options) // { "analytics.feature": "false", demo: "true", "analytics.demo": "false" }
if (options['analytics.demo'] === 'true') {
// ...
}
(Note that this uses ES6. For ES5 use var options = Object.assign.apply(object, test) instead, and you also need to polyfill Object.assign.)
This uses Object.assign() with the spread operator to merge the objects into one, then get the "analytics.demo" option from the new single object. It has to be accessed using bracket notation because the key has a dot in. It is compared to the string true because "false" (string) is true but false (boolean) is false.
There is more information on SO about flattening arrays and converting strings to booleans.
PS is there any way you can get the Ajax call to use proper booleans instead of strings? It would be easier to work with.
You can check if any of the items in the array matches a certain condition like so:
var isDemoEnabled = test.some(function (item) {
return item['analytics.demo'] === 'true';
});
if (isDemoEnabled) {
// Do something
}
If the values were boolean, you could remove === 'true'
Assuming you're using underscore, check out the documentation regarding find:
http://underscorejs.org/#find
Find runs a predicate function for every element in an array and returns a new array that contains every value where the predicate function returned true.
In this case we want to find if the element has a field analytics.demo
To do this we can use the underscore function _.has:
http://underscorejs.org/#has
all in all:
var result = _.find(test, function(elem) {
return _.has(elem, "analytics.demo");
}
);
You could iterate over and check if the key is given and return then the result.
function getKeyValue(array, key) {
var value;
array.some(function (a) {
if (key in a) {
value = a[key];
return true;
}
});
return value;
}
var test = [{ "analytics.feature": "false" }, { "demo": "true" }, { "analytics.demo": "false" }]
console.log(getKeyValue(test, 'analytics.demo')); // 'false' a string with this value

Categories

Resources