Let's say i have the following data
var obj = {
test: 'somedata',
scores: [
{
"points":99,
"id":"x12"
},
{
"points":21,
"id":"x13"
}
],
sites: [
{
"exercises":21,
"sid":"s12"
},
{
"exercises":23,
"sid":"s11"
}
],
history: {
key: 'value',
commits: [
{
id: 1,
value: 'thank you'
}
]
}
}
Notice that scores and sites contain arrays with unique elements based on id in scores and based on sid in sites. I want a function that does the following magic:
//will **update** obj.test to 'newdata' and return {test:'newdata'}
magicUpdate(obj, {test:'newdata'})
//will **insert** obj.newkey with with value 'value' and return {newkey: 'value'}
magicUpdate(obj, {newkey: 'value'})
//will do nothing and return {}
magicUpdate(obj, {scores: []})
//will **update** scores[0] and return {scores:[{points:3, id: "x12"}]}, as id "x12" is already in the array at index 0
magicUpdate(obj, {scores:[{points:3, id: "x12"}])
//will **insert** {points:3, id: "x14"} into obj.scores and return {scores:[{points:3, id: "x14"}]}
magicUpdate(obj, {scores:[{points:3, id: "x14"}]})
//will **update** sites[0] and return {sites:[{exercises:22, sid: "s12"}]}, as id "s12" is already in the array at index 0
magicUpdate(obj, {sites:[{exercises:22, sid: "s12"}])
//will **insert** {exercises:10, sid: "s14"} into obj.sites and return {sites:[{exercises:10, sid: "s14"}]}
magicUpdate(obj, {sites:[{exercises:10, sid: "s14"}]})
//and also be recursive ...
//will **update** obj.history.commits[0]
magicUpdate(obj, {'history.commits': [{id:1, value: 'changed'}]});
I have seen .update doing the recursion, but only if one is passing the path which should be determined automatically. Then there is .merge which internally uses _.baseMerge and comes really close to what i need though I do not understand the signature of the function.
_.merge(
{scores:[{id: 12, points:10}, {id: 13, points:10}]},
{scores:[{id: 14, points:10}, {id: 15, points:10}]}
)
// returns {scores:[{id: 14, points:10}, {id: 15, points:10}]} not the fully merged array
Can someone point me to a good direction or has achieved similar things with lodash?
The magicUpdate function you mention in your post could be achieved using lodash functions indeed.
For this implementation, I've used mostly _ .get, _ .set and _ .unionWith though I'm sure it could have been achieved using some others:
// src will be mutated. For simplicity's sake, obj is an object with only one property that represents the changes to make to src
function magicUpdate(src, obj) {
var key = _.first(_.keys(obj)),
value = _.get(obj, key),
srcValue = _.get(src, key),
comparator = function(a, b) {
var idKey = _.isUndefined(a.id) ? 'sid' : 'id';
return a[idKey] === b[idKey];
}
if (_.isArray(srcValue)) {
value = _.unionWith(value, srcValue, comparator);
}
return _.set(src, key, value);
}
As you may have noticed looking at the code, the return type is the mutated object and not what you're asking. I wasn't really sure what you wanted as a return value.
Anyway, Lodash doesn't have a built-in object difference function so it'd be necessary to develop something like that in case you wanted the difference between the old object and the modified one (you'd also have to _ .clone the object first to have a copy and be able to compare).
The idea of the function I present is to try to get the key of obj (it's the key we want to modify in src) and check if it exists and is an array. If so, we just add the two arrays, updating those in src that have the same id in obj. Due to the fact that sites, scores and history had id and sid I had to add some more logic to the comparator of the _.unionWith function.
If key doesn't exist or isn't an array, we just set it in src.
Here you have the fiddle in case you want to play with it. Hope it helps.
UPDATE
My first solution was intended for one property updated at a time. However, it seems that is possible to update more than one at the same time.
One quick solution could be to iterate over the object with the updates and update one property at a time.
function updateProperty(src, obj) {
var key = _.first(_.keys(obj)),
value = _.get(obj, key),
srcValue = _.get(src, key),
comparator = function(a, b) {
var idKey = _.isUndefined(a.id) ? 'sid' : 'id';
return a[idKey] === b[idKey];
}
if (_.isArray(srcValue)) {
value = _.unionWith(value, srcValue, comparator);
}
return _.set(src, key, value);
}
function magicUpdate(obj, src) {
_.forEach(src, function(value, key) {
updateProperty(obj, _.pick(src, key));
});
return obj;
}
Fiddle
I wrote a solution which is recursive and quite performant. See this fiddle.
function mergeRecursive(obj1, obj2) {
if (obj1.constructor == Array) {
for (var i = 0; i < obj1.length; i++) {
if (obj1[i].id == obj2.id) {
obj1[i] = obj2;
return obj1;
}
}
obj1.push(obj2);
return obj1;
}
for (var p in obj2) {
// Property in destination object set; update its value.
if (obj2[p].constructor == Array) {
obj2[p].forEach(function(arrayElement) {
obj1[p] = MergeRecursive(obj1[p], arrayElement);
});
} else if (obj2[p].constructor == Object) {
obj1[p] = MergeRecursive(obj1[p], obj2[p]);
} else {
obj1[p] = obj2[p];
}
}
return obj1;
}
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))
I created something similar to an ENUM like this:
var ContentStatusId = {
All: 0,
Production: 1,
Review: 2,
Draft: 3,
Concept: 4
}
so when I set:
var a = ContentStatusId.All
it gets the value of 0
How can I go in the other direction? If I know a = 0 and a comes from ContentStatusId then how can I get the string "All"?
Iterate over the properties until you find the one with the value you want
function findVal(obj, val) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) { // skip inherited properties
if (obj[prop] == val) {
return prop;
}
}
}
return false;
}
You'll have to iterate through the properties and check whether they equal the value on each iteration:
for (var property in ContentStatusId) {
if (ContentStatusId.hasOwnProperty(property)) {
if (ContentStatusId[property] == /*value to look for*/) {
console.log(property);
}
}
}
Demo
You can't do this directly. You'd have to store the key somewhere...
var a = ['All', ContentStatusId.All];
or, more advanced:
var a = {
source: ContentStatusId,
key: 'All',
update: function () {
this.value = this.source[this.key];
}
};
a.update();
Depending on what you have to do, you can either iterate over the object or if you have to do this more often, just create an array where you can do your reverse-lookup:
var ContentStatusIdReverse = ["All","Production",...]
ContentStatusIdReverse[0] // Yields "All"
You can create this array in the first place by iterating over your object once, and all consecutive lookups can be done via the array.
Imagine I'm given a reference to an array of similar objects, e.g. array will be the name of that array. Now I'm asked to create an array of all the values of some property that is found inside each object of that array, e.g. "user.id".
The problem is that I won't know the format of each object and where that property will reside/be nested.So "user.id" might reside in array[#].someKey (array[#].someKey["user.id"])or in array[#].someKey.someOtherKey (array[#].someKey.someOtherKey["user.id"])
Is there a function (jQuery, underscore..etc) that could create such an array ?
e.g. var arrayOfUserIds = returnArray(array, "user.id");
For example, imagine that the following is an example of such an array :
var array = [
{
"age": "13",
"type": "publish_action",
"tag": null,
"timestamp": 1398931707000,
"content": {
"action": "publish",
"user.id": "860",
"user.email": "alex#somemail.com",
"property.id": "2149",
"iteration_id": "15427",
"test_id": "6063",
"property.name" : "bloop"
}, {
....
}, {
....
}];
Based on the above, I could obviously do :
var arrayOfUserIds = [];
for (var i=0; i<array.length; i++)
{
arrayOfUserIds.push(array[i]["content"]["user.id"]);
}
But like I said, in my case I won't know about the format of the object so I can't create such a for-loop for example.
Any ideas will be much appreciated!
Thank you!
If I understand correctly, each object in someArray either contains a property user.id or an object that contains user.id...or, recursively, some object that contains someArray. You want to create an array containing only the user.id properties.
An easy way to do this would be to do a recursive examination of each object in the array until user.id is located:
// get `user.id` property from an object, or sub-object
// it is assumed that there will only be one such property;
// if there are more than one, only the first one will be returned
function getUserId(o){
if(o===null || o===undefined) return;
if(o['user.id']) return o['user.id'];
for(var p in o){
if(!o.hasOwnProperty(p)) continue;
if(typeof o[p] !== 'object') continue;
if(o[p] === null || o[p] === undefined) continue;
var id = getUserId(o[p]);
if(id) return id;
}
}
function getUserIds(arr){
return arr.map(function(e){
return getUserId(e);
});
}
If you want something a little more generic, you could write a "find" method that will find all instances of a named property in an object tree:
var find = (function(){
function find(matches, o, prop, checkPrototypeChain){
if(typeof o[prop] !== 'undefined') matches.push(o[prop]);
for(var p in o){
if(checkPrototypeChain || !o.hasOwnProperty(p)) continue;
if(typeof o[p] !== 'object') continue;
if(o[p] === null || o[p] === undefined) continue;
find(matches, o[p], prop, checkPrototypeChain);
}
}
return function(o, prop, checkPrototypeChain){
var matches = [];
find(matches, o, prop, checkPrototypeChain);
return matches;
}
})();
Then you could just map your array based on that:
var userIds = someArray.map(function(e){ return find(e, 'user.id'); });
Note that I'm glossing over properties that may be in the prototype chain, but in the find function, I added the ability to additionally search for properties in the prototype chain.
I went with the assumption that you're only working with primitives and object/array literals. In which case, the following method (using underscore) seems to do the trick.
var testSubject = {
mykey: 9,
firstArray: [
{something: 9, another: {x: 'hello', mykey: 'dude'}, mykey: 'whatever'},
{something: 9, another: {x: 'hello', mykey: 'dude2'}, mykey: 'whatever2'},
{
someArray: [
{seven: 7, mykey: 'another'},
{hasNo: 'mykey', atAll: 'mykey'}
]
}
],
anObject: {beef: 'jerky', mykey: 19}
};
function getValuesForKey(subject, searchKey) {
return _.reduce(subject, function(memo, value, key) {
if (_.isObject(value)) {
memo = memo.concat(getValuesForKey(value, searchKey));
} else if (key === searchKey) {
memo.push(value);
}
return memo;
}, []);
}
console.log(getValuesForKey(testSubject, 'mykey'));
// -> [9, "dude", "whatever", "dude2", "whatever2", "another", 19]
It only returns the list of values because they will all share the same key (i.e. the one specified). Additionally, I do believe any matching keys will be ignored if their values are not primitive (e.g. mykey: {…} or mykey: […] should be ignored). I hope it helps.
This question already has answers here:
How do I check if an array includes a value in JavaScript?
(60 answers)
Closed 29 days ago.
I need to determine if an object already exists in an array in javascript.
eg (dummycode):
var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};
carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);
now the "carBrands" array contains all instances.
I'm now looking a fast solution to check if an instance of car1, car2, car3 or car4 is already in the carBrands array.
eg:
var contains = carBrands.Contains(car1); //<--- returns bool.
car1 and car4 contain the same data but are different instances they should be tested as not equal.
Do I have add something like a hash to the objects on creation? Or is there a faster way to do this in Javascript.
I am looking for the fastest solution here, if dirty, so it has to be ;) In my app it has to deal with around 10000 instances.
no jquery
Use something like this:
function containsObject(obj, list) {
var i;
for (i = 0; i < list.length; i++) {
if (list[i] === obj) {
return true;
}
}
return false;
}
In this case, containsObject(car4, carBrands) is true. Remove the carBrands.push(car4); call and it will return false instead. If you later expand to using objects to store these other car objects instead of using arrays, you could use something like this instead:
function containsObject(obj, list) {
var x;
for (x in list) {
if (list.hasOwnProperty(x) && list[x] === obj) {
return true;
}
}
return false;
}
This approach will work for arrays too, but when used on arrays it will be a tad slower than the first option.
Why don't you use the indexOf method of javascript arrays?
Check this out: MDN indexOf Arrays
Simply do:
carBrands.indexOf(car1);
It will return you the index (position in the array) of car1. It will return -1 if car1 was not found in the array.
http://jsfiddle.net/Fraximus/r154cd9o
Edit: Note that in the question, the requirements are to check for the same object referenced in the array, and NOT a new object. Even if the new object is identical in content to the object in the array, it is still a different object.
As mentioned in the comments, objects are passed by reference in JS and the same object can exist multiple times in multiple structures.
If you want to create a new object and check if the array contains objects identical to your new one, this answer won't work (Julien's fiddle below), if you want to check for that same object's existence in the array, then this answer will work. Check out the fiddles here and in the comments.
Having been recently bitten by the FP bug reading many wonderful accounts of how neatly the functional paradigm fits with Javascript
I replicate the code for completeness sake and suggest two ways this can be done functionally.
var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};
var car5 = {name:'toyota'};
carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);
// ES6 approach which uses the includes method (Chrome47+, Firefox43+)
carBrands.includes(car1) // -> true
carBrands.includes(car5) // -> false
If you need to support older browsers use the polyfill, it seems IE9+ and Edge do NOT support it. Located in polyfill section of MSDN page
Alternatively I would like to propose an updated answer to cdhowie
// ES2015 syntax
function containsObject(obj, list) {
return list.some(function(elem) {
return elem === obj
})
}
// or ES6+ syntax with cool fat arrows
function containsObject(obj, list) {
return list.some(elem => elem === obj)
}
try Array.prototype.some()
MDN Array.prototype.some
function isBiggerThan10(element, index, array) {
return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10); // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
You could use jQuery's grep method:
$.grep(carBrands, function(obj) { return obj.name == "ford"; });
But as you specify no jQuery, you could just make a derivative of the function. From the source code:
function grepArray( elems, callback, inv ) {
var ret = [];
// Go through the array, only saving the items
// that pass the validator function
for ( var i = 0, length = elems.length; i < length; i++ ) {
if ( !inv !== !callback( elems[ i ], i ) ) {
ret.push( elems[ i ] );
}
}
return ret;
}
grepArray(carBrands, function(obj) { return obj.name == "ford"; });
I used underscore javascript library to tweak this issue.
function containsObject(obj, list) {
var res = _.find(list, function(val){ return _.isEqual(obj, val)});
return (_.isObject(res))? true:false;
}
please refer to underscore.js documentation for the underscore functions used in the above example.
note: This is not a pure javascript solution. Shared for educational purposes.
You can just use the equality operator: ==. Objects are checked by reference by default, so you don't even need to use the === operator.
try this, just make sure you're using the correct variable reference in the place of car1:
var i, car, l = cars.length;
for (i = 0; i < l; i++)
{
if ((car = cars[i]) == car1)
{
break;
}
else car = null;
}
Edit to add:
An array extension was mentioned, so here's the code for it:
Array.prototype.contains = Array.prototype.contains || function(obj)
{
var i, l = this.length;
for (i = 0; i < l; i++)
{
if (this[i] == obj) return true;
}
return false;
};
Note that I'm caching the length value, as the Array's length property is actually an accessor, which is marginally slower than an internal variable.
I would use a generic iterator of property/value over the array. No jQuery required.
arr = [{prop1: 'val1', prop2: 'val2'}, {prop1: 'val3', prop2: 'val4'}];
objectPropInArray(arr, 'prop1', 'val3'); // <-- returns true
function objectPropInArray(list, prop, val) {
if (list.length > 0 ) {
for (i in list) {
if (list[i][prop] === val) {
return true;
}
}
}
return false;
}
You could try sorting the array based on a property, like so:
carBrands = carBrands.sort(function(x,y){
return (x == y) ? 0 : (x > y) ? 1 : -1;
});
Then you can use an iterative routine to check whether
carBrands[Math.floor(carBrands.length/2)]
// change carBrands.length to a var that keeps
// getting divided by 2 until result is the target
// or no valid target exists
is greater or lesser than the target, and so on, which will let you go through the array quickly to find whether the object exists or not.
try this ,
You can use the JavaScript some() method to find out if a JavaScript array contains an object.
<script>
// An array of objects
var persons = [{name: "Harry"}, {name: "Alice"}, {name: "Peter"}];
// Find if the array contains an object by comparing the property value
if(persons.some(person => person.name === "Peter")){
alert("Object found inside the array.");
} else{
alert("Object not found.");
}
</script>
EDIT 05/18/2022
The most simple way using ES6:
const arrayContainsObject = <T extends Record<string, unknown>>(array: T[], object: T) => {
return array.some(item => Object.keys(item).every(key => item[key] === object[key]))
}
Use like so:
const arr = [{
prop1: 'value1',
prop2: 'value2'
}]
const obj1 = {
prop1: 'value1',
prop2: 'value2'
}
const obj2 = {
prop2: 'value2',
prop1: 'value1'
}
const obj3 = {
prop0: 'value0',
prop1: 'value1'
}
arrayContainsObject(arr, obj1) // true
arrayContainsObject(arr, obj2) // true, even when props are arranged in different order
arrayContainsObject(arr, obj3) // false
Previous answer, don't use (because the order of props in an object needs to be identical)
const arr = [{
prop: 'value'
}]
const obj = {
prop: 'value'
}
arr.some((e) => Object.entries(e).toString() === Object.entries(obj).toString()) // true
i know this is an old post, but i wanted to provide a JQuery plugin version and my code.
// Find the first occurrence of object in list, Similar to $.grep, but stops searching
function findFirst(a,b){
var i; for (i = 0; i < a.length; ++i) { if (b(a[i], i)) return a[i]; } return undefined;
}
usage:
var product = $.findFirst(arrProducts, function(p) { return p.id == 10 });
This function is to check for a unique field.
Arg 1: the array with selected data
Arg 2: key to check
Arg 3: value that must be "validated"
function objectUnique( array, field, value )
{
var unique = true;
array.forEach(function ( entry )
{
if ( entry[field] == value )
{
unique = false;
}
});
return unique;
}
you can use Array.find().
in your case is going to look like this
carBrands.find(function(car){
let result = car.name === 'ford'
if (result == null){
return false;
} else {
return true
}
});
if car is not null it will return the javaScript Object which contains the string 'ford'
The issue with many of the answers here is that they will NOT find an object in an array that is equal to another object. They will only search for an EXISTING object that has a pointer to it in an array.
Quick fix using lodash to see if ANY equal object is in an array:
import _ from 'lodash';
_.find(carBrands, car1); //returns object if true, undefined if false
Working Plunker using this method: https://plnkr.co/edit/y2YX9o7zkQa2r7lJ
if its possible to use es6
carBrands.filter(carBrand => carBrand.name === carX.name).length > 0
if it's true there is a similarity
You can convert both the JSON objects to string and simply check if the bigger json contains the smaller json.
console.log(JSON.stringify(carBrands).includes(JSON.stringify(car1))); // true
console.log(JSON.stringify(carBrands).includes(JSON.stringify(car5))); // false
You could also a the findIndex
var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
carBrands.push(car1);
if (carBrands.findIndex(f => f.name === car1.name) === -1) {
console.log('not contain')
} else {
console.log('contain')
}
if (carBrands.findIndex(f => f.name === car2.name) === -1) {
console.log('not contain')
} else {
console.log('contain')
}
This question already has answers here:
How to list the properties of a JavaScript object?
(18 answers)
Closed 6 months ago.
I was wondering if there was any way in JavaScript to loop through an object like so.
for(var i in myObject) {
// ...
}
But get the name of each property like this.
for(var i in myObject) {
separateObj[myObject[i].name] = myObject[i];
}
I can't seem to find anything like it on Google. They say to pass the names of the variables with them but this is not an option for what I am trying to achieve.
Thanks for any help you can offer.
Use Object.keys():
var myObject = { a: 'c', b: 'a', c: 'b' };
var keyNames = Object.keys(myObject);
console.log(keyNames); // Outputs ["a","b","c"]
Object.keys() gives you an array of property names belonging to the input object.
i is the name.
for(var name in obj) {
alert(name);
var value = obj[name];
alert(value);
}
So you could do:
seperateObj[i] = myObject[i];
Disclaimer
I misunderstood the question to be: "Can I know the property name that an object was attached to", but chose to leave the answer since some people may end up here while searching for that.
No, an object could be attached to multiple properties, so it has no way of knowing its name.
var obj = {a:1};
var a = {x: obj, y: obj}
What would obj's name be?
Are you sure you don't just want the property name from the for loop?
for (var propName in obj) {
console.log("Iterating through prop with name", propName, " its value is ", obj[propName])
}
you can easily iterate in objects
eg: if the object is
var a = {a:'apple', b:'ball', c:'cat', d:'doll', e:'elephant'};
Object.keys(a).forEach(key => {
console.log(key) // returns the keys in an object
console.log(a[key]) // returns the appropriate value
})
for direct access a object property by position...
generally usefull for property [0]... so it holds info about the further...
or in node.js 'require.cache[0]' for the first loaded external module, etc. etc.
Object.keys( myObject )[ 0 ]
Object.keys( myObject )[ 1 ]
...
Object.keys( myObject )[ n ]
Other than "Object.keys( obj )", we have very simple "for...in" loop - which loops over enumerable property names of an object.
const obj = {"fName":"John","lName":"Doe"};
for (const key in obj) {
//This will give key
console.log(key);
//This will give value
console.log(obj[key]);
}
To get the property of the object or the "array key" or "array index" depending on what your native language is..... Use the Object.keys() method.
Important, this is only compatible with "Modern browsers":
So if your object is called, myObject...
var c = 0;
for(c in myObject) {
console.log(Object.keys(myObject[c]));
}
Walla! This will definitely work in the latest firefox and ie11 and chrome...
Here is some documentation at MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
IN ES5
E.G. you have this kind of object:
var ELEMENTS = {
STEP_ELEMENT: { ID: "0", imageName: "el_0.png" },
GREEN_ELEMENT: { ID: "1", imageName: "el_1.png" },
BLUE_ELEMENT: { ID: "2", imageName: "el_2.png" },
ORANGE_ELEMENT: { ID: "3", imageName: "el_3.png" },
PURPLE_ELEMENT: { ID: "4", imageName: "el_4.png" },
YELLOW_ELEMENT: { ID: "5", imageName: "el_5.png" }
};
And now if you want to have a function that if you pass '0' as a param - to get 'STEP_ELEMENT', if '2' to get 'BLUE_ELEMENT' and so for
function(elementId) {
var element = null;
Object.keys(ELEMENTS).forEach(function(key) {
if(ELEMENTS[key].ID === elementId.toString()){
element = key;
return;
}
});
return element;
}
This is probably not the best solution to the problem but its good to give you an idea how to do it.
Cheers.
As of 2018 , You can make use of Object.getOwnPropertyNames() as described in Developer Mozilla Documentation
const object1 = {
a: 1,
b: 2,
c: 3
};
console.log(Object.getOwnPropertyNames(object1));
// expected output: Array ["a", "b", "c"]
Using Object.keys() function for acquiring properties from an Object, and it can help search property by name, for example:
const Products = function(){
this.Product = "Product A";
this.Price = 9.99;
this.Quantity = 112;
};
// Simple find function case insensitive
let findPropByName = function(data, propertyName){
let props = [];
Object.keys(data).forEach(element => {
return props.push(element.toLowerCase());
});
console.log(props);
let i = props.indexOf(propertyName.toLowerCase());
if(i > -1){
return props[i];
}
return false;
};
// calling the function
let products = new Products();
console.log(findPropByName(products, 'quantity'));
When you do the for/in loop you put up first, i is the property name. So you have the property name, i, and access the value by doing myObject[i].
These solutions work too.
// Solution One
function removeProperty(obj, prop) {
var bool;
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
if (keys[i] === prop) {
delete obj[prop];
bool = true;
}
}
return Boolean(bool);
}
//Solution two
function removeProperty(obj, prop) {
var bool;
if (obj.hasOwnProperty(prop)) {
bool = true;
delete obj[prop];
}
return Boolean(bool);
}
Quick & dirty:
function getObjName(obj) {
return (wrap={obj}) && eval('for(p in obj){p}') && (wrap=null);
}