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

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]))

Related

Check if properties in TypeScript Object are empty

I have an object that looks like this:
protected products: {
color: string[],
brand: number[],
} = {};
I want to check if the properties of products are null (simply Array(0)). How can I do it?
I am using "target": "es2015".
You could probably use lodash _.isEmpty(value):
_.isEmpty(null);
// => true
_.isEmpty(true);
// => true
_.isEmpty(1);
// => true
_.isEmpty([1, 2, 3]);
// => false
_.isEmpty({ 'a': 1 });
// => false
Could try this:
const checkEmptyObj = (object) => {
// gets an array of the values for each kv pair in your object
const values = Object.values(object);
// if you add kv pairs with non array types, will have to adjust this
// removes all zero length arrays (or strings) from values array
const nonEmptyValues = values.filter(value => value.length > 0)
// if any items are in the nonEmptyValues array, return false
return nonEmptyValues.length < 1
}
This is not a catch all solution, it needs more work for use beyond your stated case. Specifically, it only works on objects of one level deep. If you are passing in a nested object, you'll have to adjust the function to be recursive. If you expect to have other data types, you will have to do some handling of those inside the filter function (the .length call will fail on numbers and objects, among others).
After more thought, I like this solution more.
return values.every(value => value.length === 0)
For checking if all the arrays are empty, you can approach it as follow:
This is assuming that all values are arrays
let products = {color: [],brand: []};
let allEmpty = Object.values(products).every(({length}) => !Boolean(length));
console.log(allEmpty);
As the argument is an array, we can use the destructuring assignment as follow:
{length} // Basically to extract the attribute length
The number 0 is considered falsy, so we can do explicit type coercion (or type casting) on values as follow:
!Boolean(length) // Coerce to boolean the number from arr.length
// The negation is needed because if the length === 0 that
// means the array is empty, so we want the result
// as true in our handler for the function every

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;
});

Dynamically compare two arrays

I'm trying to compare two arrays, one being called values and other one called feeds.
The feeds array has multiple set of values, how can I check which feed contains the correct set of values to match?
Fiddle link: https://jsfiddle.net/v7ussmbb/1/
I understand the async nature, ie console.log rules before the loop completes which is fine, I just need the comparison part.
I would iterate all your feeds until one matches all the rules, to achieve that I would do something like this: https://jsfiddle.net/canastro/v7ussmbb/4/
// Hold the active feed
var active_feed = '';
// Iterate until one item matches all rules
const found = feeds.some(function(item) {
//console.log('item: ', item);
// Check if all rules match
const match = item.rules.some(function(rule) {
// Get rule to apply by comparing values keys with the rule id
let ruleToApply;
Object.keys(values).some(function(key) {
const isRule = key === String(rule.id);
if (isRule) { ruleToApply = values[key]; }
return isRule;
});
return ruleToApply === rule.value;
});
if (match) { active_feed = item; }
return match;
});
console.log('active_feed: ', active_feed);
To achieve this I used some function:
some() executes the callback function once for each element present in
the array until it finds one where callback returns a truthy value (a
value that becomes true when converted to a Boolean). If such an
element is found, some() immediately returns true. Otherwise, some()
returns false. callback is invoked only for indexes of the array which
have assigned values; it is not invoked for indexes which have been
deleted or which have never been assigned values.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some

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

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.

Javascript: Determine if all of the elements in the array are keys in the object

I am trying to figure out if all of the elements in an array are keys in the object.
var obj = { name: 'Computer', cost: '$1,000' };
var myArray = [ 'name', 'cost', 'bio' ]; //another example would be var myArray = [];
for(var x = 0; x < myArray.length; x++){
if (myArray[x] in obj)
{
return true;
}
}
How can I check if all of the elements in an array are keys in the object?
Do it the other way around. If you find someone in the array who is NOT in the object then you return false. If you reach the end of the loop then you return true because all the keys were in the object.
Depending on what you want, this might do the trick:
function hasKeys(obj, keys) {
for (var i=0; i != keys.length; ++i) {
if (!(keys[i] in obj))
return false;
}
return true;
};
One subtlety you need to ask yourself: do you want to know if the object has the keys directly (i.e. not somewhere in its prototype stack?) If so, then replace keys[i] in obj with obj.hasOwnProperty(keys[i])
function hasKeys(obj, keys) {
return keys.every(Object.prototype.hasOwnProperty.bind(obj));
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every states, "The every method executes the provided callback function once for each element present in the array until it finds one where callback returns a falsy value (a value that becomes false when converted to a Boolean). If such an element is found, the every method immediately returns false. Otherwise, if callback returned a true value for all elements, every will return true. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values" (emphasis mine).
Array.some() makes for a clean solution.
// object in question
var obj = { ... };
// keys that need to be present in the object
var keys = [ ... ];
// iterate through the whitelist until we find a key that doesn't exist in the object. If all exist, that means Array.some() is false.
var valid = !keys.some(function(key) {
return !obj.hasOwnProperty(key);
});
An alternative solution would be using a similar concept, but with Array.every(). It is to note that this will generally be slower because it always has to touch every element in the whitelist.
// iterate through the whitelist, making sure the object has each key.
var valid = keys.every(obj.hasOwnProperty);
This problem can be expressed in terms of set inclusion: does the set of property keys completely include the array of required keys? So we can write it as
includes(Object.keys(obj), arr)
So now we just need to write includes.
function includes(arr1, arr2) {
return arr2.every(function(key) {
return contains(arr1, key);
}
}
For contains, we could use Underscore's _.contains, or just write it ourselves:
function contains(arr, val) {
return arr.indexOf(val) !== -1;
}
If we are interested in conciseness at the possible expense of readability, we could shorten our definition of includes to use Function#bind instead of the anonymous function:
function includes(arr1, arr2) {
return arr2.every(contains.bind(0, arr1));
}
Now we have functions we can use for other things, instead of mixing up the two different aspects of the problem--the keys of an object, and set inclusion. If we really want to write an all-in-one function, it becomes the somewhat more readable:
function hasMany(obj, arr) {
return arr.every(_.contains.bind(0, Object.keys(obj));
}
If we want more readability, like we were writing a novel:
function object_has_required_keys(object, required_keys) {
var object_keys = Object.keys(object);
function key_is_present(key) {
return object_keys.indexOf(key) !== -1;
}
return required_keys.every(key_is_present);
}
Underscore's _.intersection
If we're lazy (or smart), we could use Underscore's _.intersection to implement includes:
function includes(arr1, arr2) {
return _.intersection(arr1, arr2).length === arr2.length;
}
The idea is to take the intersection, and if the first array includes the second entirely, then the intersection will contain all the elements of the second array, which we can check by comparing their lengths.
Using ES6 sets
Thinking ahead to ES6, we could implement include using its sets, which ought to be faster:
function includes(arr1, arr2) {
var set = new Set(arr1);
return arr2.every(Set.prototype.has.bind(set));
}

Categories

Resources