Alright then implement the objContains function: must search inside a nested object for a pair {key: value} specific. Both the object and the property name and its value will be received by parameter.
In the event that it finds the indicated value at any level of the object, it must return true, otherwise return false.
Ex:
const user = {
id: 6,
email: 'homero#maxpower.com',
Personal info: {
name: 'Homer Simpson',
address: {
street: 'Avenue AlwaysLive',
number: 742,
neighborhood: 'Springfield',
state: 'Massachusetts'
}
}
}
Case that returns true -> objContains (user, "neighborhood", "Springfield");
Case that returns false -> objContains (user, "employment", "Employee in nuclear plant");
Hint: use typeof to determine if the value of a property is an object to apply
there the recursion
this is what i've try
var objContains = function (obj, prop, value) {
object var = prop.value
if (typeof prop.value === obj) {
var current = this.value;
objContains (object, prop, current)
} else if (this.prop === prop && prop.value === value) {
return true;
} else {
return false;
}
}
AssertionError: expected false to equal true
32 | }
33 | it ('It should return true if it finds the property and its correct value', fun
ction () {
> 34 | expect (objContains (user, "neighborhood", "Springfield")). to.equal (true);
35 | });
36 | it ('Should return false if the property is NOT found', function () {
37 | expect (objContains (user, "employment", "Employee at nuclear power plant")). to.equal (
false);
There are a couple of problems:
typeof prop.value checks the type of the property with the literal name value on whatever prop is. You've described prop as the name of an object property, so it doesn't make sense to try to look for value on it. You want to look on obj, not prop, using the syntax described in this question's answers. I don't think it's writing it for you to say that that looks like this: if (obj[prop] === value)
If you don't find the property with that value on obj, you should be looking through the other properties on obj and, if any of them refer to objects, calling your function with the object they refer to (and prop and value) and, if the function returns true, return true. Looping through the properties on the object is covered by this question's answers.
So the general form of a solution would be:
See if obj has a property whose name is the value of prop that matches the value of value. If so, return true.
If not, loop through obj's other properties and check the type of their values; for each one that's an object (typeof is "object" and the value isn't null), call your function again with that property value, prop, and value. If it returns true, return true. If not, keep looping.
I'm purposefully just giving an indication of where to go, rather than writing the code, because this seems like an assignment we should help you with rather than doing for you.
I loop through each key in object... if the the key refers to an object itself then recursively call... else check to see if that's the key we're looking for and if so check its value... using the |= operator makes it easy to not worry about results of individual calls... we just care if the conditions are true ANYWHERE in the tree..
const user = {
id: 6,
email: 'homero#maxpower.com',
"Personal info": {
name: 'Homer Simpson',
address: {
street: 'Avenue AlwaysLive',
number: 742,
neighborhood: 'Springfield',
state: 'Massachusetts'
}
}
}
var objContains = function(obj, prop, value) {
var returnValue = false;
var keyArray = Object.keys(obj);
keyArray.forEach(property => {
if (typeof(obj[property]) == 'object') {
returnValue |= objContains(obj[property], prop, value);
} else if (property == prop) {
returnValue |= obj[property] == value;
}
});
return !!returnValue;
}
console.log(objContains(user, 'neighborhood', 'Springfield'));
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'm currently having a problem with a deep search in a json object and even though i thought this issue must have been covered alot, I wasn't able to find anything that was really helpful so far (and I actually found alot, also this thread. Maybe I've been looking at code for too long today but it didn't really help me)
Basically what i want is pretty simple. I have a JSON-Object thats pretty deep filled with objects. All i want is a function that returns an array with all objects that contain a given Key-Value-Pair. I made this function to return the first found object which works just fine
deepSearch: function(Obj, Key, Value){
var returned = [];
var result = false;
var searchObj = function(_Obj, _Key, _Value){
if(_Obj[_Key]===_Value){
return _Obj;
} else {
return false;
}
}
result = searchObj(Obj, Key, Value);
$.each(Obj, function(key, value){
if(typeof(Obj[key]) === 'object' && Obj[key]!== null && !result)
result = customGeneralFunctions.objects.deepSearch(Obj[key], Key, Value);
if(result) return result;
});
return result;
}
Now I want to change it to return an array contianing all Objects with that pair. I've been trying for a while now and I think it wouldnt be a change too hard but I just can't wrap my head around it. Maybesomeone has an idea that helps me. Thanks in advance and
Greetings Chris
A safe deep object search?
Can't let this pass 3 answers with examples, all flawed. And all illustrate some classic Javascript coding got-ya's
null is an Object
UPDATE an answer has been changed.
As the code is no longer visible I will just leave the warning when iterating an object's properties and you use typeof to check if you have an object be careful to check for null as it is also of type "object"
getObject returns to early and fails to find additional objects nested inside objects that meet the condition. Though easily fixed by removing the return it will still throw a TypeError: Cannot read property 'find' of null if the object being searched contains an array with null in it.
for in the indiscriminate iterator
UPDATE an answer has been removed.
I have added the removed code as an example in the snippet below function deepSearch is fatally flawed and will more likely throw a RangeError: Maximum call stack size exceeded error then find the object you are looking for. eg deepSearch({ a:"a"},"id",3);. When using for in you should type check as it will iterate a string as well as an object's properties.
function deepSearch(object, key, value) {
var filtered = [];
for (var p in object)
if (p === key && object[p] === value) filtered.push(object);
else if (object[p]) filtered = filtered.concat(deepSearch(object[p], key, value));
return filtered;
}
Dont trust the callback.
Alex K search passed most tests (within reasonable scope of the question) but only if the code in the form of the comment // tip: here is a good idea to check for hasOwnProperty would have been included.
But that said the function has a flaw (and inefficiency) as it will call predicate on all properties of an object, and I can think of plenty of scenarios in which the function can return many references to the same object eg the reciprocal search for objects with property key NOT with value predicate = (key,val)=>{return key === "id" && val !== 3}.
The search should only add one entry per object thus we should test the object not the properties. We can never trust the callback to do what we expect.
And as it is the accepted answer I should point out that Array.concat should really not be used as it is in this situation. Using closure is much more efficient and allows you to not have to pass the current state to each recursion.
Circular reference.
The flaw to floor them all.
I am not to sure if it is relevant as the question does state that the data is from the form JSON and hence would be free of any circular reference (JSON can not reference).
But I will address the problem and several solutions.
A circular reference is simply an object referencing itself. For example.
var me = {};
me.me = me;
That will crash all the other answers if passed as an argument. Circular references are very common.
Some solutions.
First solution is to only accept data in the form of a JSON string and equally return the data as a JSON string (so balance is maintained and the universe does not explode). Thus eliminating any chance of a circular reference.
Track recursion depth and set a limit. Though this will stop a callstack overflow
it will not prevent the result being flawed as a shallow circular reference can create duplicate object references.
The quick down and dirty solution is a simple try catch around a JSON.stringify and throw TypeError("Object can not be searched"); for those on that side of the data bus..
The best solution is to decycle the object. Which in this case is very amenable to the actual algorithm we are using. For each unique object that is encountered we place it in an array. If we encounter an object that is in that array we ignore it and move on.
A possible solution.
Thus the general purpose solution, that is safe (I hope) and flexible. Though it is written for ES6 so legacy support will have to be provided in the form of babel or the like. Though it does come with a BUT!
// Log function
function log(data){console.log(data)}
// The test data
var a = {
a : "a",
one : {
two : {
find : "me",
data : "and my data in one.two"
},
twoA : {
four : 4,
find : "me",
data : "and my data in one.twoA"
}
},
two : {
one : {
one : 1,
find : "not me",
},
two : {
one : 1,
two : 1,
find : "me",
data : "and my data in two.two"
},
},
anArray : [
null,0,undefined,/./,new Date(),function(){return hi},
{
item : "one",
find : "Not me",
},{
item : "two",
find : "Not me",
extra : {
find : "me",
data : "I am a property of anArray item 1",
more : {
find : "me",
data : "hiding inside me"
},
}
},{
item : "three",
find : "me",
data : "and I am in an array"
},{
item : "four",
find : "me",
data : "and I am in an array"
},
],
three : {
one : {
one : 1,
},
two : {
one : 1,
two : 1,
},
three : {
one : 1,
two : {
one : {
find : "me",
data : "and my data in three.three.two.one"
}
}
}
},
}
// Add cyclic referance
a.extra = {
find : "me",
data : "I am cyclic in nature.",
}
a.extra.cycle = a.extra;
a.extraOne = {
test : [a],
self : a,
findme : a.extra,
};
if(! Object.allWith){
/* Non writeable enumerable configurable property of Object.prototype
as a function in the form
Object.allWith(predicate)
Arguments
predicate Function used to test the child property takes the argument
obj the current object to test
and will return true if the condition is meet
Return
An array of all objects that satisfy the predicate
Example
var test = {a : { key : 10, data: 100}, b : { key : 11, data: 100} };
var res = test.allWith((obj)=>obj.key === 10);
// res contains test.a
*/
Object.defineProperty(Object.prototype, 'allWith', {
writable : false,
enumerable : false,
configurable : false,
value : function (predicate) {
var uObjects = [];
var objects = [];
if (typeof predicate !== "function") {throw new TypeError("predicate is not a function")}
(function find (obj) {
var key;
if (predicate(obj) === true) {objects.push(obj)}
for (key of Object.keys(obj)) {
let o = obj[key];
if (o && typeof o === "object") {
if (! uObjects.find(obj => obj === o)) {
uObjects.push(o);
find(o);
}
}
}
} (this));
return objects;
}
});
}else{
console.warn("Warn!! Object.allWith already defined.");
}
var res = a.allWith(obj => obj.find === "me");
res.forEach((a,i)=>(log("Item : " + i + " ------------"),log(a)))
Why are you searching through unknown data structures?
It works for all the test cases I could come up with, but that is not at all the definitive test. I added it to the Object.prototype because you should not do that!!! nor use such a function or derivative thereof.
This is the first time I have written such a function, and the reason is that I have never had to write something like that before, I know what the data looks like and I dont have to create dangerous recursive iterators to find what is needed.. If you are writing code and you are not sure of the data you are using there is something wrong in the design of the whole project.
Hopefully this will help you to solve your task.
Lets use recursion to search deep into object.
Also lets make it more generic.
// search function takes object as a first param and
// a predicate Function as second predicate(key, value) => boolean
function search(obj, predicate) {
let result = [];
for(let p in obj) { // iterate on every property
// tip: here is a good idea to check for hasOwnProperty
if (typeof(obj[p]) == 'object') { // if its object - lets search inside it
result = result.concat(search(obj[p], predicate));
} else if (predicate(p, obj[p]))
result.push(
obj
); // check condition
}
return result;
}
Lets test it!
var obj = {
id: 1,
title: 'hello world',
child: {
id: 2,
title: 'foobar',
child: {
id: 3,
title: 'i should be in results array '
}
},
anotherInnerObj: {
id: 3,
title: 'i should be in results array too!'
}
};
var result = search(obj, function(key, value) { // im looking for this key value pair
return key === 'id' && value === 3;
});
Output:
result.forEach(r => console.log(r))
// Object {id: 3, title: "i should be in results array "}
// Object {id: 3, title: "i should be in results array too!"}
You've created a returned array. First, push the result of searchObj() into it. Then in your loop, if you get a result, concat() it to returned. Finally, return returned at the end of the function. That should do it...
You could use a simplified version and
check if object not truthy or object is not an object, then return
check if given key and value match, then add the actual object to the result set,
get the keys and iterate over the properties and call the function again.
At last, the array with the collected objects is returned.
function getObjects(object, key, value) {
function iter(o) {
if (!o || typeof o !== 'object') {
return;
}
if (o[key] === value){
result.push(o);
}
Object.keys(o).forEach(function (k) {
iter(o[k]);
});
}
var result = [];
iter(object);
return result;
}
var object = { id: 1, title: 'hello world', child: { id: null, title: 'foobar', child: { id: null, title: 'i should be in results array ' } }, foo: { id: null, title: 'i should be in results array too!' }, deep: [{ id: null, value: 'yo' }, { id: null, value: 'yo2' }] };
console.log(getObjects(object, 'id', null));
.as-console-wrapper { max-height: 100% !important; top: 0; }
is there any function or any fast way to check if some value in our object startsWith e.g asd
Example:
let obj = {
'child' : {
'child_key': 'asdfghhj'
},
'free': 'notasd',
'with': 'asdhaheg'
}
// check here if our obj has value that startsWith('asd')
Regards
Use #trincot's solution if you really don't care about which node/value matched. It's straightforward, well-written, and solves your problem very effectively.
If you want more than just a Boolean value as the result of your digging, read along ...
I really doubt your need for this, but if your object is significantly large, you will want an early exit behaviour – what this means is that as soon as a match is found, iteration through your input data will stop and true/false result will be returned immediately. #trincot's solution offers early exit, but solutions that using map, filter, or reduce offer no such behaviour.
findDeep is much more useful than just checking if a string value starts with another string value – it takes a higher-order function that is applied for each leaf node in your data.
This answer uses my findDeep procedure to define a generic anyStartsWith procedure by checking if findDeep returns undefined (no match)
It will work any any input type and it will traverse Object and Array child nodes.
const isObject = x=> Object(x) === x
const isArray = Array.isArray
const keys = Object.keys
const rest = ([x,...xs]) => xs
const findDeep = f => x => {
let make = (x,ks)=> ({node: x, keys: ks || keys(x)})
let processNode = (parents, path, {node, keys:[k,...ks]})=> {
if (k === undefined)
return loop(parents, rest(path))
else if (isArray(node[k]) || isObject(node[k]))
return loop([make(node[k]), make(node, ks), ...parents], [k, ...path])
else if (f(node[k], k))
return {parents, path: [k,...path], node}
else
return loop([{node, keys: ks}, ...parents], path)
}
let loop = ([node,...parents], path) => {
if (node === undefined)
return undefined
else
return processNode(parents, path, node)
}
return loop([make(x)], [])
}
const startsWith = x => y => y.indexOf(x) === 0
const anyStartsWith = x => xs => findDeep (startsWith(x)) (xs) !== undefined
let obj = {
'child' : {
'child_key': 'asdfghhj'
},
'free': 'notasd',
'with': 'asdhaheg'
}
console.log(anyStartsWith ('asd') (obj)) // true
console.log(anyStartsWith ('candy') (obj)) // false
You'll see this is kind of a waste of findDeep's potential, but if you don't need it's power then it's not for you.
Here's the real power of findDeep
findDeep (startsWith('asd')) (obj)
// =>
{
parents: [
{
node: {
child: {
child_key: 'asdfghhj'
},
free: 'notasd',
with: 'asdhaheg'
},
keys: [ 'free', 'with' ]
}
],
path: [ 'child_key', 'child' ],
node: {
child_key: 'asdfghhj'
}
}
The resulting object has 3 properties
parents – the full object reference to each node in the matched value's lineage
path – the path of keys to get to the matched value (stack reversed)
node – the key/value pair that matched
You can see that if we take the parent object as p and reverse the path stack, we get to the matched value
p['child']['child_key']; //=> 'asdfghhj'
Here is a function with mild ES6 usage:
function startsWithRecursive(obj, needle) {
return obj != null &&
(typeof obj === "object"
? Object.keys(obj).some( key => startsWithRecursive(obj[key], needle) )
: String(obj).startsWith(needle));
}
// Sample data
let obj = {
'child' : {
'child_key': 'asdfghhj'
},
'free': 'notasd',
'with': 'asdhaheg'
};
// Requests
console.log( 'obj, "asd":', startsWithRecursive(obj, 'asd' ) );
console.log( 'obj, "hello":', startsWithRecursive(obj, 'hello' ) );
console.log( 'null, "":', startsWithRecursive(null, '' ) );
console.log( 'undefined, "":', startsWithRecursive(undefined, '' ) );
console.log( '"test", "te":', startsWithRecursive('test', 'te' ) );
console.log( '12.5, 1:', startsWithRecursive(12.5, 1 ) );
Explanation:
The function is recursive: it calls itself as it goes through a nested object structure. The value passed as obj can fall in one of the following three categories:
It is equivalent to null (like also undefined): in that case neither a recursive call, nor a call of the startsWith method can be made: the result is false as this value obviously does not start with the given search string;
It is an object: in that case that object's property values should be inspected. This will be done through recursive calls. The some method makes sure that as soon a match has been found, the iteration stops, and no further property values are inspected. In that case some returns true. If none of the property values matched, some returns false;
It is none of the above. In that case we cast it to string (by applying the String function) and apply startsWith on it.
The value calculated in the applicable step will be returned as function result. If this was a recursive call, it will be treated as return value in the some callback, ...etc.
Note that this function also returns the correct result when you call it on a string, like so:
startsWithRecursive('test', 'te'); // true
Non-Recursive Alternative
In answer to comments about potential stack limitations, here is an alternative non-recursive function which maintains a "stack" in a variable:
function startsWithRecursive(obj, needle) {
var stack = [obj];
while (stack.length) {
obj = stack.pop();
if (obj != null) {
if (typeof obj === "object") {
stack = stack.concat(Object.keys(obj).map( key => obj[key] ));
} else {
if (String(obj).startsWith(needle)) return true;
}
}
}
return false;
}
You can recursively iterate object properties and check if property starts with prefix using find function:
function hasPropertyStartingWith(obj, prefix) {
return !!Object.keys(obj).find(key => {
if (typeof obj[key] === 'object') {
return hasPropertyStartingWith(obj[key], prefix)
}
if (typeof obj[key] === 'string') {
return obj[key].startsWith(prefix)
}
return false
})
}
console.log(hasPropertyStartingWith(obj, 'asd'))
You may get away with something as simple as using a RegExp on a JSON string, something like
var obj = {
'child': {
'child_key': 'asdfghhj'
},
'free': 'notasd',
'with': 'asdhaheg'
};
function customStartsWith(obj, prefix) {
return new RegExp(':"' + prefix + '[\\s\\S]*?"').test(JSON.stringify(obj));
}
console.log('obj, "asd":', customStartsWith(obj, 'asd'));
console.log('obj, "hello":', customStartsWith(obj, 'hello'));
console.log('null, "":', customStartsWith(null, ''));
console.log('undefined, "":', customStartsWith(undefined, ''));
console.log('"test", "te":', customStartsWith('test', 'te'));
console.log('12.5, 1:', customStartsWith(12.5, 1));
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.1/es6-shim.js"></script>
Update: Another recursive object walker that will work in a shimmed environment. This is just an example and it is easily customised.
var walk = returnExports;
var obj = {
'child': {
'child_key': 'asdfghhj'
},
'free': 'notasd',
'with': 'asdhaheg'
};
function customStartsWith(obj, prefix) {
var found = false;
walk(obj, Object.keys, function(value) {
if (typeof value === 'string' && value.startsWith(prefix)) {
found = true;
walk.BREAK;
}
});
return found;
}
console.log('obj, "asd":', customStartsWith(obj, 'asd'));
console.log('obj, "hello":', customStartsWith(obj, 'hello'));
console.log('null, "":', customStartsWith(null, ''));
console.log('undefined, "":', customStartsWith(undefined, ''));
console.log('"test", "te":', customStartsWith('test', 'te'));
console.log('12.5, 1:', customStartsWith(12.5, 1));
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.1/es6-shim.js"></script>
<script src="https://rawgithub.com/Xotic750/object-walk-x/master/lib/object-walk-x.js"></script>
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.