I've got a object like this:
{"status":200,
"success":true,
"result": [ {"Description":"", "Year":"", "Price/STK":"", "Main Cat":"Fruits"} ]
}
I have distinct lists I need to use, and the Price key can be: Price/STK, Price/Box, Price/Btl or Price.
I know I can get the value using, for example, data.result['Price/STK'], but I don't want to check every key, I'd like to search for the price and just use.
How would I determine if a word ('Price*', for example) is part of a key and get that value?
There's no built in way to do this, you have to iterate and check each key.
You could just create a convenient function :
function matchKey(objectToSearch, keyToFind) {
for (var k in objectToSearch) {
if ( k.toLowerCase().indexOf(keyToFind.toLowerCase()) !== -1)
return objectToSearch[k];
}
return null;
}
matchKey({year : 2015, "Price/STK" : "value"}, "price"); // returns "value"
FIDDLE
You could solve this problem easily using lodash (or underscore)
_.findKey(obj, function(key) { return _.startsWith(key, 'Price')})
This finds the first key that starts with price.
You can get the property names of an object using Object.keys, and then use indexOf to search for a value, but it does an exact match and doesn't take a regular expression as an argument.
So you have to loop over all the property names until you find the one you want. There are built–in iterators to help:
var obj = {"status":200,
"success":true,
"result": [ {"Description":"desc",
"Year":"yr",
"Price/STK":"price/stk",
"Main Cat":"Fruits"}
]
};
function getValueLike(obj, prop){
var re = new RegExp('^' + prop);
var value;
Object.keys(obj).some(function(prop) {
if (re.test(prop)) {
value = obj[prop];
return true;
}
});
return value;
}
document.write(getValueLike(obj.result[0], 'Price')); // price/stk
A version that uses indexOf on the property name might be faster and is a little less code:
function getValueLike(obj, prop){
var value;
Object.keys(obj).some(function(key) {
if (key.indexOf(prop) == 0) {
value = obj[key];
return true;
}
});
return value;
}
which can be reduced to:
function getValueLike(obj, prop, value){
Object.keys(obj).some(function(key) {return key.indexOf(prop) == 0 && ((value = obj[key]) || true)});
return value;
}
which also allows a default value to be passed to value, but it's a little too obfuscated for me.
Using an arrow function:
function getValueLike(obj, prop, value){
Object.keys(obj).some(key => key.indexOf(prop) == 0 && ((value = obj[key]) || true));
return value;
}
Filter the set of keys on the result array's object for "Price", and then return the value associated with that. I made a function for it as an example.
function selectPrice(obj){
return obj.result[0][
Object.keys(obj.result[0]).filter(function(el){
return el.indexOf("Price") > -1
})[0]
]
}
var data = {"status":200,
"success":true,
"result": [ {"Description":"", "Year":"", "Price/STK":"6", "Main Cat":"Fruits"} ]
};
document.write(selectPrice(data));
Related
I have an object like this :
That is just for example....
{a:"aaaa",
b:{
b1:"1b1b1b",
b2:"2bb22b",
b3:{
mykey:"value to find",
some:"same",
},
},
}
I know the key "mykey" but I don't know where is it , I don't know the path...
I cant use like this to find the value...
myObj.a.b.maykey
because i don't know where is the key "mykey"
I only know that I have in my object this Key
I have to find "value to find",
how can i find a value of myKey?
thanks
Assuming you know the key is myKey and you're looking for it somewhere in the object graph, one option is to use a depth-first traversal recursive function (similar to that used by the DOM for querySelector). This is much simpler than the name suggests. :-) See comments:
function findFirstValue(data, key) {
// ASSERTION: data is an object
// Loop through the properties of the object
for (const [name, value] of Object.entries(data)) {
// Found the key?
if (name === key) {
// Return the value
return value;
}
// If the value is an object, recurse
if (typeof value === "object") {
const found = findFirstValue(value, key);
if (found !== undefined) {
// Found during recursion
return found;
}
}
}
// Not found
return undefined; // Explicit, but this is effectively what would happen anyway
}
const found = findFirstValue({
a: "aaaa",
b: {
b1: "1b1b1b",
b2: "2bb22b",
b3: {
mykey: "value",
some: "same",
},
},
}, "mykey");
console.log(found);
That returns undefined if not found. You could use a flag value instead (so that if the key is found but the value actually is undefined, you can tell the difference). That's a minor tweak to the above. But if you can assume the value won't actually be undefined, undefined makes a good flag value to use.
You can do that by recursion.
let obj = {a:"aaaa",
b:{
b1:"1b1b1b",
b2:"2bb22b",
b3:{
mykey:"value",
some:"same",
},
},
}
function find(obj,givenKey){
for(let key in obj){
//checks if key's value is object
if(typeof obj[key] === "object"){
//find 'givenKey' inside that object
let keyValue = find(obj[key],givenKey)
//if 'givenKey' is found in that object
if(keyValue){
//return that key's value
return keyValue
}
}
//if key's value is not object
else{
//if key match given key then it return the value of key
if(key === givenKey) return obj[key]
}
}
}
console.log(find(obj,'mykey'))
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
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));
}
I wanted to check if the an object has a property of something and its value is equal to a certain value.
var test = [{name : "joey", age: 15}, {name: "hell", age: 12}]
There you go, an array of objects, now I wanted to search inside the object and return true if the object contains what I wanted.
I tried to do it like this:
Object.prototype.inObject = function(key, value) {
if (this.hasOwnProperty(key) && this[key] === value) {
return true
};
return false;
};
This works, but not in an array. How do I do that?
Use the some Array method to test your function for each value of the array:
function hasValue(obj, key, value) {
return obj.hasOwnProperty(key) && obj[key] === value;
}
var test = [{name : "joey", age: 15}, {name: "hell", age: 12}]
console.log(test.some(function(boy) { return hasValue(boy, "age", 12); }));
// => true - there is a twelve-year-old boy in the array
Btw, don't extend Object.prototype.
-- for the property --
if(prop in Obj)
//or
Obj.hasOwnProperty(prop)
-- for the value ---
Using "Object.prototype.hasValue = ..." will be FATAL for js but Object.defineProperty let you define properties with enumerable:false (default)
Object.defineProperty(Object.prototype,"hasValue",{
value : function (obj){
var $=this;
for( prop in $ ){
if( $[prop] === obj ) return prop;
}
return false;
}
});
just for experiment test if a NodeList has an Element
var NL=document.QuerySelectorAll("[atr_name]"),
EL= document.getElementById("an_id");
console.log( NL.hasValue(EL) )
// if false then #an_id has not atr_name
For array, of course you have to browse that array with for
for(var i = 0 ; i < yourArray.length; i++){
if(yourArray[i].hasOwnProperty("name") && yourArray[i].name === "yourValue") {
//process if true
}
}
Typically you'll use something like Object.first:
// search for key "foo" with value "bar"
var found = !!Object.first(test, function (obj) {
return obj.hasOwnProperty("foo") && obj.foo === "bar";
});
Assuming that Object.first will return some falsy value when it doesn't find a match.
Object.first is not a native function but check on of the popular frameworks, they're bound to have one.
Here is another solution for checking if the object has the property but the value of property is not set. Maybe the property value has 0, null or an empty string.
array.forEach(function(e){
if(e.hasOwnProperty(property) && Boolean(e[property])){
//do something
}
else{
//do something else
}
});
Boolean() is the trick here.
What I essentially need to do is, given a json like
{
"1" : "a",
"7" : "something"
"3" : {
"1" : "blah"
}
}
Convert these to an array (say x).
x[1] = "a"
x[7] = "something"
x[3] = y (where y[1] = "blah")
You'll need to deserialize the JSON into a non-array object graph, and then copy the properties into arrays. I'm not aware of any shortcut for it.
The basic loop once you've deserialized the JSON into obj is roughly:
var ar;
var key;
ar = [];
for (key in obj) {
if (obj.hasOwnProperty(key)) {
ar[key] = obj[key];
}
}
...except you'll have to detect that obj[key] is an object and recurse, which I'll leave as an exercise for the reader.
Note that in JavaScript, arrays aren't really arrays. Depending on your use-case, you may not need to do the conversion from object to Array at all.
I'm pretty sure that in Javascript, you can access this:
x = {
"1" : "a",
"7" : "something",
"3" : {
"1" : "blah"
}
}
Like this:
alert( x["1"] );
which should alert "a". As people already mentioned in the comments above, an array in JS is an "object" already, and there isn't a difference between accessing them these two different ways.
Edit:
Yeah I just tested it and it works. Also, I tried this:
alert( x[1] );
That is, I tried it with the "number" 1, not the "string" "1". It still worked. Yes it's a very strange programming language.
I think this is pretty close:
function parse_obj(obj)
{
var array = [];
var prop;
for (prop in obj)
{
if (obj.hasOwnProperty(prop))
{
var key = parseInt(prop, 10);
var value = obj[prop];
if (typeof value === "object")
{
value = parse_obj(value);
}
array[key] = value;
}
}
return array;
}
http://jsfiddle.net/shaggyfrog/DFnnm/
This works for me:
var obj = JSON.parse('{"1":"a","7":"something","3":{"1":"blah"}}');
var keys = Object.keys(obj).sort();
// Make obj look like it's an array by taking the highest value
// key and using it to give obj a length property.
obj.length = parseInt( keys[keys.length] ) + 1;
var arr = Array.prototype.slice.call(obj, 0);
arr now looks like this:
[undefined, "a", undefined, Object, undefined, undefined, undefined, "something"]
Ok, so it hasn't turned the 'inner' JSON object into an array, but a quick recursive loop doing the same thing as above should sort that out.