I got an object like this :
var obj1 = {foo: false, bar: ''};
var obj2 = {foo: false, bar: '1'};
var obj3 = {foo: true, bar: ''};
var obj4 = {foo: true, bar: '1'};
I want a simple function to check those objects if all of their values are false or not. In this given example only obj1 should trigger a false - cause all of their values are false. obj2, obj3 and obj4 own at least one value which is true.
Is there a simple solution to do this?
As a one-liner:
!Object.keys(obj1).some(function(k) {return obj1[k];});
// Array.some returns true if any callback returns true
// You want true if all return false, aka if none return true
// So just negate Array.some
As a more readable method:
var ok = true, k;
for( k in obj1) if( obj1.hasOwnProperty(k)) {
if( obj1[k]) {
ok = false;
break;
}
}
You can use the some function:
[ob1, ob2, ob3, obj4].some(function(obj) { return obj.foo })
For each object: if every property value is false return false, otherwise true:
var out = [obj1, obj2, obj3, obj4].map(function (obj) {
return !Object.keys(obj).every(function (p) {
return !obj[p];
})
}); // [false, true, true, true]
DEMO
There is a flaw with the other implementations of .some() you want to return values where all properties are a falsy value, not just where any property is a falsy value as per the OP requirements.
So this will do it
function isFalse(obj) {
return Object
.keys(obj)
.every(function (k) {
return !obj[k];
});
}
See jsFiddle for proof https://jsfiddle.net/0se3yh62/
The other benefit of Object.keys it will only return own properties so you don't have to check in a manual loop.
const isObjectFilled = obj => Object.values(obj).filter(value => !!value).length > 0
isObjectFilled(obj1) // false
isObjectFilled(obj2) // true
isObjectFilled(obj3) // true
isObjectFilled(obj4) // true
"The Object.values() method returns an array of a given object's own enumerable property values" (MDN)
Once i've this array of values, i'm going to filter it by removing each falsy values.
.filter(value => !!value) will filter the array by returning only truthy values.
If the length of the filtered array is greater than 0, it means that at least one of the object's values is truthy. Then the function will return true
If the filtered array is empty, it means that all of the object's values are falsy. Then the function will return false
I assume you want a dynamic function that would work on any object, so how about just iterating all of the object's indexes?
function objIsFalsy(obj) {
for(var i in obj) {
if(obj[i]) return false;
}
return true;
}
Follow these steps :-
Put all your object variables in an array.
Make a foreach loop for the above array.
Inside the loop check for object key's value.
Loop on your object:
function isFalsyObj(obj) {
for(var elt in obj) if (obj[elt]!=false) return false;
return true;
}
var obj1 = {foo: false, bar: ''};
var obj2 = {foo: false, bar: '1'};
var obj3 = {foo: true, bar: ''};
var obj4 = {foo: true, bar: '1'};
console.log(isFalsyObj(obj1));//true
console.log(isFalsyObj(obj2));//false
console.log(isFalsyObj(obj3));//false
console.log(isFalsyObj(obj4));//false
Check this
isvalidObj(obj1); // false
isvalidObj(obj2); // true
function isvalidObj(obj){
for(var i in obj){
if(obj[i]) return true;
}
return false;
}
Related
If I have an array like this:
var arr = ['one','two','three'];
I can access different parts by doing this:
console.log(arr[1]);
How can I access object properties by their order rather than by key?
Example:
var obj = {
'something' : 'awesome',
'evenmore' : 'crazy'
},
jbo = {
'evenmore' : 'crazy',
'something' : 'awesome'
};
How would I get the first property for each object–"something" from obj and "evenmore" from jbo–without explicitly using the property name?
Now, a few of you seem to think I'm after something like:
console.log(obj['something']);
This is not the case, I'm specifically looking to target the index, just like the first example - if it's possible.
"I'm specifically looking to target the index, just like the first example - if it's possible."
No, it isn't possible.
The closest you can get is to get an Array of the object's keys, and use that:
var keys = Object.keys( obj );
...but there's no guarantee that the keys will be returned in the order you defined. So it could end up looking like:
keys[ 0 ]; // 'evenmore'
keys[ 1 ]; // 'something'
The only way I can think of doing this is by creating a method that gives you the property using Object.keys();.
var obj = {
dog: "woof",
cat: "meow",
key: function(n) {
return this[Object.keys(this)[n]];
}
};
obj.key(1); // "meow"
Demo: http://jsfiddle.net/UmkVn/
It would be possible to extend this to all objects using Object.prototype; but that isn't usually recommended.
Instead, use a function helper:
var object = {
key: function(n) {
return this[ Object.keys(this)[n] ];
}
};
function key(obj, idx) {
return object.key.call(obj, idx);
}
key({ a: 6 }, 0); // 6
You can use the Object.values() method if you dont want to use the Object.keys().
As opposed to the Object.keys() method that returns an array of a given object's own enumerable properties, so for instance:
const object1 = {
a: 'somestring',
b: 42,
c: false
};
console.log(Object.keys(object1));
Would print out the following array:
[ 'a', 'b', 'c' ]
The Object.values() method returns an array of a given object's own enumerable property values.
So if you have the same object but use values instead,
const object1 = {
a: 'somestring',
b: 42,
c: false
};
console.log(Object.values(object1));
You would get the following array:
[ 'somestring', 42, false ]
So if you wanted to access the object1.b, but using an index instead you could use:
Object.values(object1)[1] === 42
You can read more about this method here.
var obj = {
'key1':'value',
'2':'value',
'key 1':'value'
}
console.log(obj.key1)
console.log(obj['key1'])
console.log(obj['2'])
console.log(obj['key 1'])
// will not work
console.log(obj.2)
Edit:
"I'm specifically looking to target the index, just like the first example - if it's possible."
Actually the 'index' is the key. If you want to store the position of a key you need to create a custom object to handle this.
Yes, it is possible. We can define getters for each index, and return the property value, in the constructor method of the class. See this code.
class className {
constructor() {
this.name = "Bikram";
this.age = 8;
this.x = 89;
this.y = true;
//Use a for loop and define the getters (with the object property's index as its "name") for each property using Object.defineProperty()
for (let i = 0; i < Object.keys(this).length; i++) {
Object.defineProperty(this, i, {
get: function() {
return Object.values(this)[i]}
});
}
}
}
var b = new className();
console.log(b[0]); // same as b.name ("Bikram")
console.log(b[1]); // = b.age (8)
console.log(b[2]); // = b.x (89)
console.log(b[3]); // = b.y (true)
Edit: If you want to change the properties by their indices, which, of course, you do. Then, just define a corresponding setter for each property in the Object.defineProperty() method. It will look like:
// Insert this in place of the old one
Object.defineProperty(this, i, {
get: function() {
return Object.values(this)[i];
},
set: function(newValue) {
this[Object.keys(this)[i]] = newValue;
}
})
console.log(b[0]); // "Bikram"
b[0] = "Bikram Kumar";
console.log(b[0]); // "Bikram Kumar"
And now you have an "array-like-object" whose properties can be accessed or modified either by property key or its index :D
A side note: Notice that Object.keys() and Object.values() only return the enumerable properties. If you just declare a property and not assign it to any value, the Object.[key/value]s() methods will leave that in the returned array, because by default they are not enumerable. This might become confusing for the indices so defined (except the case the undeclared property is the last one).
To get around this, there is a simple way, if you want some property to have a index, but don't wanna assign it now. Just set it to undefined, and it will now be enumerable, and the indices won't be affected.
by jquery you can do this:
var arr = $.map(obj,function(value, key) {
return value;
});
alert(obj[0]);
Get the array of keys, reverse it, then run your loop
var keys = Object.keys( obj ).reverse();
for(var i = 0; i < keys.length; i++){
var key = keys[i];
var value = obj[key];
//do stuff backwards
}
you can create an array that filled with your object fields and use an index on the array and access object properties via that
propertiesName:['pr1','pr2','pr3']
this.myObject[this.propertiesName[0]]
I went ahead and made a function for you:
Object.prototype.getValueByIndex = function (index) {
/*
Object.getOwnPropertyNames() takes in a parameter of the object,
and returns an array of all the properties.
In this case it would return: ["something","evenmore"].
So, this[Object.getOwnPropertyNames(this)[index]]; is really just the same thing as:
this[propertyName]
*/
return this[Object.getOwnPropertyNames(this)[index]];
};
let obj = {
'something' : 'awesome',
'evenmore' : 'crazy'
};
console.log(obj.getValueByIndex(0)); // Expected output: "awesome"
Sure it is possible, but it is not as immediate as accessing to an array by its indexes, but still possible and even relatively simple actually: in fact you don't have to struggle too much. This code sample will show how:
var obj = {
'alfa' : 'value of obj the key alfa',
'beta' : 'value of obj the key beta',
'gamma' : 'value of obj the key gamma'
};
var jbo = {
'alfa' : 'value of jbo the key alfa',
'beta' : 'value of jbo the key beta',
'gamma' : 'value of jbo the key gamma'
};
alert ( obj[Object.keys(obj)[1]] );
alert ( jbo[Object.keys(jbo)[1]] );
/* you can even put it into a for loop as follows */
for (i=0;i<3;i++)
{
document.writeln ( "<br>This could be even a piece of HTML: " + obj[Object.keys(obj)[i]] );
document.writeln ( "<br>This could be even a piece of HTML: " + jbo[Object.keys(jbo)[i]] );
}
Explication:
As you know the Object.keys() statement returns an array of all enumerable properties (which means all keys) of the object you type into its round parenthesis.
So the only thing you need is to indicate the index after that array, which will returns the key literal found at that index.
The key itself is "digested" as usual by the object which returns the value at that key.
If you are not sure Object.keys() is going to return you the keys in the right order, you can try this logic instead
var keys = []
var obj = {
'key1' : 'value1',
'key2' : 'value2',
'key3' : 'value3',
}
for (var key in obj){
keys.push(key)
}
console.log(obj[keys[1]])
console.log(obj[keys[2]])
console.log(obj[keys[3]])
You can also construct a function that will return the value of a property by accepting two parameters: the object and the "index" (order position)
function getValue(obj, index) {
let keysArray = Object.keys(obj)
let key = keysArray[index]
return obj[key]
}
Usage example getValue(obj, 2)
Snippet
let obj = {a: 'dog', b: 'cat', c: 'mouse'}
function getValue(obj, index){
let keysArray = Object.keys(obj)
let key = keysArray[index]
return obj[key]
}
console.log(getValue(obj, 2))
Here is my code. I know it's not entirely strict but please shed some light on why the let...in does not work properly here.
const object1 = {here: 1, object: 3};
const obj = {here: 1, object: 2};
function comp(a, b) {
if (typeof a == typeof b) {
let arra = Object.keys(a);
let arrb = Object.keys(b);
for (let key in arra){
if (a[key] == b[key]) return true
}
return false
}
}
console.log(comp(obj, object1))
The above prints true but it is supposed to print false
You're getting true because you return true in your for loop whenever a key value from one object equals the key-value pair of another object. So when your code sees the here property, it will return true, thus stopping your function from running any further code.
You need to remove this check, and only return false in your for loop, such that your for loop will only complete if it never returns (ie: all key-value pairs are equal).
Moreover, the for..in loop will loop over the keys in an object, so, there is no need to get the keys of your objects (using Object.keys) into an array (as then you'll be looping over the keys of an array (ie: the indexes)).
However, with that being said, you can use Object.keys to help with another issue. You can use it to get the number of properties in both objects, as you know the two objects are not the same if they don't have the same number of properties in them
See example below:
const object1 = {
here: 1,
object: 3
};
const obj = {
here: 1,
object: 3
};
function comp(a, b) {
if (typeof a == typeof b) {
if(Object.keys(a).length !== Object.keys(b).length) {
return false; // return false (stop fruther code execution)
}
for (let key in a) { // loop through the properties of larger object (here I've chosen 'a') - no need for Object.keys
if (a[key] != b[key])
return false; // return false (stops any further code executing)
}
return true; // we only reach this point if the for loop never returned false
}
return false; // we reach this point when the two types don't match, and so we can say they're not equal
}
console.log(comp(obj, object1))
You should use for..of (or just a plain old for) instead of for..in which is only used on Objects. You're reading array indices right now, not actual key names. Object.keys returns an Array of key names, not an Object.
Also stop returning early; Right now you return immediately after the first key check.
You need to check for actual values and not property names.
Also, you need to check if b has more properties than a, because if it is the same, but has one property more, it will still output true.
const tester = {here: 1, object: 3};
const obj1 = {here: 1, object: 2};
const obj2 = {here: 1, object: 3};
const obj3 = {here: 1, object: 3, test: 1};
const obj4 = {here: 1, test: 1};
function comp(a, b) {
if (typeof a == typeof b && Object.keys(a).length == Object.keys(b).length) { // Check for the length of the keys array, because if the length is different, they might have different properties
// Dont use Object.keys here. You don't need the keys, you need the objects
for (let key in a){
if (a[key] != b[key])
return false; // If one key property of a does not match b, return false
}
return true; // If nothing returns false, return true
}
return false; // If they are not the same type, return false
}
console.log(comp(tester, obj1))
console.log(comp(tester, obj2))
console.log(comp(tester, obj3))
console.log(comp(tester, obj4))
Here is your problem:
for (let key in arra){
if (a[key] == b[key]) return true
}
return false
}
You should perform the exact opposite while iterating through the object:
for (let key in a){ // a not arra
if (a[key] !== b[key]) return false
}
return true
}
And ommit these lines:
let arra = Object.keys(a);
let arrb = Object.keys(b);
Array.prototype.some() function can be used as below:
const object1 = {here: 1, object: 3, r:4};
const obj = {here: 1, r:4, object: 3};
function comp(a, b) {
if (typeof a == typeof b) {
let arra = Object.keys(a);
return !arra.some(key => { return a[key] != b[key] })
}
}
console.log(comp(obj, object1))
My original task was to create a function that returned a boolean value if my data object contained a truthy value.
I do not care what value or key is truthy, only that the data contains a truthy value.
var fruits = { apples: false, oranges: true, bananas: true }
When iterating over this object the return should be true because there are true values within.
The following function did work:
return Object.values(fruits).some(function(k) {
return k;
});
However I cannot use Object.value nor the array.some due to IE compatibility
The suggested Polyfill is to use .map instead to get each value, however but the next step is removing .some() - I have tried using .filter() but this takes me back to the original problem that it returns the key that is truthy not merely an assertion that a truthy value exists in the databaset
If you need old-style JavaScript, then just go for a plain for loop:
function hasTruthy(fruits) {
for (var key in fruits) {
if (fruits.hasOwnProperty(key) && fruits[key]) return true;
}
return false;
}
You don't even need that hasOwnProperty check.
var fruits = {
apples: false,
oranges: true,
bananas: true
}
function hasTruthyValue(obj) {
for (let key in obj) {
if (obj[key]) {
return true;
}
}
}
console.log(hasTruthyValue(fruits)); //true
In the given object all values of properties are the same.
var obj = {
property1: 'Some Value',
property2: 'Some Value',
property3: 'Some Value',
property4: 'Some Value'
}
The function checkEquality should return true if all values are the same and false otherwise.
I can do the following to achieve it:
function checkEquality () {
var compare = obj.propery1;
for (var key in obj) {
if (obj[key] !== compare) {
return false;
}
}
return true;
}
But this solution by far not the best.
You could use Array#every for it.
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.
var obj = { propery1: 'Some Value', propery2: 'Some Value', propery3: 'Some Value', propery4: 'Some Value' },
equal = Object.keys(obj).every(function (k, i, kk) {
return !i || obj[kk[0]] === obj[k];
});
console.log(equal);
Great answer by #Nina, I'd just like to add something different using reduce and ES6 syntax:
const sameValues = (obj ) => {
let keys = Object.keys( obj );
let initial = obj[ keys[0] ];
// val will be either the initial value or false
let val = keys.reduce( (prev, cur) => ( obj[cur] === prev ? prev : false ), initial );
return val === initial;
}
https://jsfiddle.net/9tb5mdoL/
In JavaScript, I need to know if all object items are set to true.
If I have the following object:
var myObj = {title:true, name:true, email:false};
I could write something like this :
if(myObj.title && myObj.name && myObj.email){
/*Some code */
};
But I am looking for the simplest way to write it. eg :
if(myObj all is true){
/*Some code */
};
I might have another object with 10-20 items inside it, and will need to know if all are true.
With ES2017 Object.values() life's even simpler.
Object.values(yourTestObject).every(item => item)
Even shorter version with Boolean() function [thanks to xab]
Object.values(yourTestObject).every(Boolean)
Or with stricter true checks
Object.values(yourTestObject)
.every(item => item === true)
In modern browsers:
var allTrue = Object.keys(myObj).every(function(k){ return myObj[k] });
If you really want to check for true rather than just a truthy value:
var allTrue = Object.keys(myObj).every(function(k){ return myObj[k] === true });
How about something like:
function allTrue(obj)
{
for(var o in obj)
if(!obj[o]) return false;
return true;
}
var myObj1 = {title:true, name:true, email:false};
var myObj2 = {title:true, name:true, email:true};
document.write('<br />myObj1 all true: ' + allTrue(myObj1));
document.write('<br />myObj2 all true: ' + allTrue(myObj2));
A few disclaimers: This will return true if all values are true-ish, not necessarily exactly equal to the Boolean value of True. Also, it will scan all properties of the passed in object, including its prototype. This may or may not be what you need, however it should work fine on a simple object literal like the one you provided.
Quickest way is a loop
for(var index in myObj){
if(!myObj[index]){ //check if it is truly false
var fail = true
}
}
if(fail){
//test failed
}
This will loop all values in the array then check if the value is false and if it is then it will set the fail variable, witch will tell you that the test failed.
You can use every from lodash
const obj1 = { a: 1, b: 2, c: true };
const obj2 = { a: true, b: true, c: true };
_.every(obj1, true); // false
_.every(obj2, true); // true