Iterate thought javascript object to see if it has a certain value - javascript

I'm trying to figure out the best way to interate through a javascript object to see if one of the keys is set to a certain value. I understand I can do a foreach loop but I feel like there is an easier way.
var myObject = {
a: false,
b: false,
c: false,
x: false
}
Id like a quick way to return a true if at least one of those values is set to true, and false if all are false.

You have to iterate, but you can do something like this
var hasTrue = Object.keys(myObject).some(function(key) {
return myObject[key];
});
this uses Array.some and stops as soon as a true value is encountered.
FIDDLE

To return the key that has yourValue as its value, just do:
var yourValue = true;
var key = Object.keys(myObject).filter(function (i) {
return myObject[i] === yourValue;
})[0];
It will return undefined if no key found.
If you dont need the key and you only need to know if the value is in your object, you can just use the some method:
var hasValue = Object.keys(myObject).some(function (i) {
return myObject[i] === yourValue;
});

var any_true = false;
JSON.stringify(myObject, function(key, value) {
if (value === true) any_true = true;
});
This uses the callback feature of JSON.stringify. It has the advantage that it finds any true value, even in nested objects.

Related

How can I check if an object is returned from a filter call?

I'm trying to return true or false, but the filter method returns a new array with the object that matches the return. Is it possible to just return true? I have looked at the includes prototype but that seems to return the entire object as well.
I have tried the following...
let check = this.props.data.filter(obj => {
return obj.idNum.includes(value);
});
let check = this.props.data.map(obj => {
return obj.idNum.includes(value);
});
let check = this.props.data.filter(obj => {
return obj.idNum.includes(value) : true ? false;
});
I'm really just trying to make check true if the array of objects contains the value I'm looking for. I'm checking the idNum for each object for a match.
Take a look at the array .some method. You could use it like so:
let check = this.props.data.some(obj => {
return obj.idNum === value;
});
The some method returns true if the function given to it returns true for any of the array elements.

how to get value from object with a partial index value javascript

I have an object which contains alot of keys and values. I can get any value using the index. But I dont have the full index, I have a part of it, would I be able to get the value based on a part of the index.
Example:
c = {'select':'MyValue',...}
I can get the value using indexing as shown below:
c['select'] = 'MyValue'
I tried to create this function which searches exact value:
function search(nameKey, c){
for (var i=0; i < c.length; i++) {
if (c[i].select === nameKey) {
return c[i];
}
}
}
c['select'] will return 'MyValue' but I need to do something like c['Sel'] or c['select'] or c['Select']or c['selected']to return the same 'MyValue'
Well the logic doesn't seem to be very clear and it's not quite relevant how it would be matching the key.
But This is a function that may help in the specific cases you showed:
function search(nameKey, obj) {
if (obj.hasOwnProperty(nameKey)) {
return obj[nameKey];
} else {
var res = Object.keys(obj).filter(function(k) {
return (k.toLowerCase().indexOf(nameKey.toLowerCase()) > -1) || (nameKey.toLowerCase().indexOf(k.toLowerCase()) > -1);
});
return res ? obj[res] : false;
}
}
Explanation:
First we use Object#hasOwnProperty() to check if the object has the searched name as key/property, we return it's value, this will avoid looping all the keys.
Otherwise we use Object.keys() to get the keys of the object.
Then we use Array#filter() method over the keys array to check if a relevant key exists we
return it's value, otherwise we return false.
Demo:
function search(nameKey, obj) {
if (obj.hasOwnProperty(nameKey)) {
return obj[nameKey];
} else {
var res = Object.keys(obj).filter(function(k) {
return (k.toLowerCase().indexOf(nameKey.toLowerCase()) > -1) || (nameKey.toLowerCase().indexOf(k.toLowerCase()) > -1);
});
return res ? obj[res] : false;
}
}
var c = {
'select': 'MyValue'
};
console.log(search("Sel", c));
Here's an one liner (!):
Assuming your array is in data and the partial index value is in selector:
const result = Object.keys(data).filter(k => k.toLowerCase().indexOf(selector.toLowerCase()) != -1).map(k => data[k]);
The above code returns an Array (coz, there may be more than one match). If you just need a first element, just do result[0].
You can use Object.keys() to get an array of the property names.
Then find first match using Array#find() to get the key needed (if it exists)
const data = {
aaaa: 1,
bbbbbbb: 2,
cccc: 3
}
function search(nameKey, obj) {
nameKey = nameKey.toLowerCase();// normalize both to lowercase to make it case insensitive
const keys = Object.keys(obj);
const wantedKey = keys.find(key => key.toLowerCase().includes(nameKey));
return wantedKey ? obj[wantedKey] : false;
}
console.log('Term "a" value:', search('a',data))
console.log('Term "bb" value:', search('bb',data))
console.log('Term "X" value:', search('X',data))
Since search criteria is vague I simply found any match anywhere in the property name and didn't look past the first one found

Javascript check for existing object in Array

I have some simple objects in an Array. I want to add new objects to the Array only if they are not already in it, based on an object property.
var o = {text: 'foo'}
var a = [o]
var checkExisting = function (list, obj) {
list.forEach(function(elem) {
if (elem.text === obj) {
return true
}
}
}
checkExisting(a, 'foo')
This doesn't work. I can't figure out why. Any help or alternatives would be great.
Because you can't return value from callback in forEach, you can use for, like this
var checkExisting = function (list, obj) {
for (var i = 0, len = list.length; i < len; i++) {
if (list[i].text === obj) {
return true;
}
}
}
This can be done very similar to how you are but with .every() because .forEach() always returns undefined. So you can't chain it either.
.every() runs a method over every element like .forEach() but if it receives a false value it will abort. Finally if every iteration returns true it will return true to the caller otherwise it will return false.
Because we return false to make it abort when a value is found (so it wont keep iterating), we then have to flip the value it returns before we return it from checkExisting.
So using that you could do something like:
var checkExisting = function (list, obj) {
return !list.every(function(elem) {
return elem.text !== obj;
});
}
Obviously you would have to extend that for error handling if the object doesn't have a property text etc.
See fiddle: http://jsfiddle.net/reLsqhkm/
And docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every

Replacing underscore or lodash _.each with vanilla for loop

I'm wanting to replace the following code to no longer rely on the _.each() function of underscore.js or lodash.js:
function fset(data) {
_.each(dataDefault, function(item, key) {
var val = ( data[key] ? data[key] : dataDefault[key] );
$rootScope.meta[key] = val;
});
};
Ideally, I want to use a vanilla JavaScript for loop, but I don't understand how the _.each() function in underscore/lodash works to replace it...
Something like:
for(var i=0; i<data.length;i++) {
var val = ( data[key] ? data[key] : dataDefault[key] );
$rootScope.meta[key] = val;
}
But, I don't know how to get the key and item in this way...
dataDefault looks like:
var dataDefault = {
title: null,
description: null
};
An example of calling the function would be:
meta.fset({
title: 'Hello world',
description: 'DESC'
});
Try this:
Object.keys(dataDefault).forEach(function (key) {
var value = dataDefault[key]
// iteration code
})
With for..in you have to use hasOwnProperty to exclude inherit properties.
So, if I'm interpreting your logic correctly, what you're trying to do is loop through the keys in your defaults object, and if the object you're inspecting doesn't have that key, you want to add that key to the object and assign its value to the default value, is that correct? Any limitations on browser level?
The quickest way to do it if you know for sure what the default data object looks like would be to use a for..in loop:
var data = {}; // or wherever you get it from)
for (var key in defaultData){
data[key] = data[key] || defaultData[key];
}
That assumes that data.key is non-null and non-false. If false or null is a valid value (and your default is not null or false), then you'll want to make a bit more effort at ascertaining the existence of the key and type of the value. But based on your example, you're not worried about that.

jquery.inArray() function not working

I am having a array as follows
var nameIDHashMap = [];
nameIDHashMap.push({
key: name,
value: xmlLength
});
startToEnd.push({
key: $(this).attr("startFrom"),
value: $(this).attr("endTo")
});
I m trying to use the inArray() function like shown below
var variablestart = startToEnd[0].key;
alert("The variable Start is :"+variablestart);
var toEnd;
if(jQuery.inArray(variablestart,nameIDHashMap) > -1) {
alert('found');
}
if ($.inArray(variablestart, nameIDHashMap) != -1)
{
alert("Found");
// toEnd = startToEnd[connectWindow].value
}
else
alert("Fail");
I dont know why always the else loop is called. None of the if loop is getting called. Both of the array has that same key present. Please let me know where I am doing wrong.Thanks!
variablestart is a property of an element in the array, not an element in the array.
var nameIDHashMap = [];
nameIDHashMap.push({
key: 'foo',
value: 'bar'
});
$.inArray(nameIDHashMap[0].key, nameIDHashMap); // this is not an element, -1
$.inArray(nameIDHashMap[0], nameIDHashMap); // this is an element, 0
You are essentially trying to equate the object { key: 'foo', value: 'bar' } to the string 'foo', which are not equal.
http://jsfiddle.net/jbabey/kgYSe/
That's not how .inArray() works. It searches for an array element that's equal to the value you pass in. It doesn't have any provisions for a comparison function.
Even if it did work, what you're assembling there isn't a "hash table". If you want to do efficient lookups by key, you can just create named properties on a simple object:
var map = {};
map.someKey = someValue;
The .inArray() method and anything like it performs a linear-time search through the array, and that's not a very efficient way to do things if you're going to have an "interesting" number of key/value pairs.
edit — if you really must keep a linear unindexed list of named properties, you could use a lookup function like this:
function find( list, key, test ) {
test = test || function(e) { return e ? e.key == key : false; };
for (var i = 0; i < list.length; ++i)
if (test(list[i])) return i;
return -1;
}
To use that, you'd just do:
if (find(nameIDHashMap, someKey) >= 0) {
alert("Found!");
}

Categories