comparing and pushing array of objects in javascript - javascript

array1:
[{"Attribute1":"Apple","Attribute2":"jacob.nelson#cognizant.com"}]
array2:
[{"Attribute1":"orange"}]`
I want to replace the value of "Attribute1" in array1 to value of "Attribute1" in array2.
My output should be like
[{"Attribute1":"orange","Attribute2":"jacob.nelson#cognizant.com"}]
I'm new to javascript.Am stuck here.Any help will be much appreciated.

What you showed us is JSON objects representation.
In this case you have an array of objects, so if you do next:
>>ar=[{"Attribute1":"Apple","Attribute2":"jacob.nelson#cognizant.com"}]
[Object]
This says that you have one object in an array, then yoou have to get it:
>>obj=ar[0]
Object {Attribute1: "Apple", Attribute2: "jacob.nelson#cognizant.com"}
Then if you need to replace something in objects, you have to treat them like OBJECTS!
>>ar2=[{"Attribute1":"orange"}]
>>obj2=ar2[0]
>>obj1.Attribute1=obj2.Attribute1
And that's all!
TIP if you have many objects, loop over them:
>>objects_array=[
{"Attribute1":"Apple","Attribute2":"jacob.nelson#cognizant.com"},
{"Attribute1":"Cucumber","Attribute2":"asd#qwe.com"}
]
[Object, Object]
>>for obj in objects_array {
obj.Attribute1='Whatever'
}

This is probably overkill for this single case, however here it is:
Using Object.extend
// adds Object.extend if it does not already exist
if (typeof Object.extend !== 'function') {
Object.extend = function (d /* DESTINATION */, s /* SOURCE */) {
for (var k in s) {
if (s.hasOwnProperty(k)) {
var v = s[k];
if (d.hasOwnProperty(k) && typeof d[k] === "object" && typeof v === "object") {
Object.extend(d[k], v);
} else {
d[k] = v;
}
}
}
return d;
};
}
you can get the desired results by doing this:
var arr1 = [{"Attribute1":"Apple","Attribute2":"jacob.nelson#cognizant.com"}],
arr2 = [{"Attribute1":"orange"}];
arr1 = Object.extend(arr1, arr2);
>> [{"Attribute1":"orange","Attribute2":"jacob.nelson#cognizant.com"}]
But like it is mentioned in the comments; if this is the only case, do this by hand.

Related

Counting how many properties with a typeof value of 'object' are inside another object

I've been doing some iterations to obtain a certain amount of values.
$.each(Obj, function(k,v){
$.each(v, function(j,l){
$.each(l, function(r,s){
if(l.hasOwnProperty(r) && typeof s === 'object'){
}
})
})
})
In this code, you'll see that I'm iterating over an object named "Obj". Inside of it we'll have a few amount of arrays and objects, because is a very complex structure. But let's cut the chatter. Once we arrive to this part...
$.each(l, function(r,s){
if(l.hasOwnProperty(r) && typeof s === 'object'){
}
})
You'll see that we have a conditional. In that conditional I'm checking for those properties "r" that have a typeof value of 'object'. So, if I do a console check of "r" inside my conditional, I will actually see those specific properties.
So, here's the thing. Why am I doing this? Well I'm building a variable that will ONLY store those "l" elements that have a child property with 'object' as a typeof value. That's actually working, but the problem is that, for my purposes, I need this variable not only to work as intended, but also to store only the elements that have MORE THAN ONE property with 'object' as a typeof value.
So, let's consider this case:
If I have two objects like the following...
Obj1: [{"key":"value", "key":"value", "key":"[{"key":"value", "key":"value"}, { "key":"value", "key":"value"}]"}]
Obj1: [{"key":"value", "key":"value", "key":"[{"key":"value", "key":"value"}, { "key":"value", "key":"value"}]", "key":"[{"key":"value", "key":"value"}, { "key":"value", "key":"value"}]"}]
I want my variable to store ONLY the second one, because it has 2 values with objects inside of it.
So, In my conditional I would like to use some kind of logic that let me know not only if my "l" element has an object inside of it, but also, how many of them do I have, and if they're lesser than one, then my console log shouldn't bring them up.
Hope it's clear enough.
My idea is to design something that would be recursive and would not blow the stack:
function inspect (obj,f,e,ledger) {
/*obj is the object to inspect,
f is the call back,
e is an internal reference to setTimeout,
ledger is the array that will be populated*/
var ledger = ledger || [],
probObjCount = 0;
f = f || false,
e && e.value ? clearTimeout(e.value) : void(0);
e = e || {};
e.value = setTimeout(function(){f && f.call(ledger,ledger);},50);
if(obj instanceof Array){
obj.forEach(function(d,i){
(typeof d === "object") && window.requestAnimationFrame(function(){
inspect(d,f,e,ledger);
})
})
return;
}
for (var i in obj) {
if(!obj.hasOwnProperty(i)){
continue;
}
if(typeof obj[i] === "object") {
++probObjCount;
!function(obj){
window.requestAnimationFrame(function(){
inspect(obj,f,e,ledger);
})
}(obj[i]);
}
}
if(probObjCount >= 2){
ledger.push(obj);
}
}
You provide this function 2 things, an object to inspect and a callback that will be provided with a ledger (an array) that will be the list of objects that fits your criteria:
var x = [{"key1":"value", "key2":"value", "key3":[{"key4":"value", "key5":"value"}, { "key6":"value", "key7":"value"}]}];
inspect(x,function(l){console.log(l)});
//after a few seconds:
//[]
var x = [{"key1":"value", "key2":"value", "key3":[{"key4":"value", "key5":"value"}, { "key6":"value", "key7":"value"}], "key8":[{"key9":"value", "key10":"value"}, { "key11":"value", "key12":"value"}]}]
inspect(x,function(l){console.log(l)});
//[{…}]
Above 2 are your examples, now I will turn your 1st example into an example that would be accepted:
var x = [{"key1":"value", "key2":"value", "key3":[{"key4":["value"], "key5":["value"]}, { "key6":"value", "key7":"value"}]}]
inspect(x,function(l){console.log(l)});
//[{…}] you will get {"key4":["value"], "key5":["value"]}

How to compare JavaScript objects obtained by parsing JSON?

wtf1 = JSON.parse('{"asdf": "jkl"}');
wtf2 = JSON.parse('{"asdf": "jkl"}');
wtf1 == wtf2; // false
wtf1 === wtf2; // false
I’ve recently stumbled upon the above problem. This counter-intuitive situation makes it hard to, for example, find a specific object in an array deep in a JSON hierarchy.
Any way to somehow compare such objects?
For simple objects you can stringify them again (with ordered keys) and compare strings. For example:
var wtf1 = JSON.parse('{"a": "a", "b": "b"}');
var wtf2 = JSON.parse('{"b": "b", "a": "a"}');
var s1 = JSON.stringify(wtf1, Object.keys(wtf1).sort());
var s2 = JSON.stringify(wtf2, Object.keys(wtf2).sort());
console.log('wtf1 is equal to wtf2: ', (s1 == s2));
For nested objects with prototypes etc you should probably use _.isEqual or any other lib that provides deep equality test.
Note, that in general it's not trivial to correctly implement deep equality test for objects, it's not as simple as iterating and comparing keys/values. However, since the "objects were obtained by parsing JSON" you can skip most of complications and recursively stringify nested values.
I think it's better to just compare them before you parse into objects. But this only works if they are exactly the same, including the order of the properties
var obj1 = {name: "potato", age: 10}
var obj2 = {name: "potato", age: 10}
console.log(obj1 == obj2) //false
console.log(JSON.stringify(obj1) == JSON.stringify(obj2)) //true
var obj1 = {name: "potato", age: 10}
var obj2 = {age: 10, name: "potato"}
console.log(obj1 == obj2) //false
console.log(JSON.stringify(obj1) == JSON.stringify(obj2)) //also false
You cannot compare objects ( as theyre differnet ), but you can iterate over each property, and compare them (and recursively check if theyre objects again):
function compare(obj1,obj2){
//check for obj2 overlapping props
if(!Object.keys(obj2).every(key=>obj1.hasOwnProperty(key))){
return false;
}
//check every key for being same
return Object.keys(obj1).every(function(key){
//if object
if((typeof obj1[key]=="object" )&&( typeof obj2[key]=="object")){
//recursively check
return compare(obj1[key],obj2[key]);
}else{
//do the normal compare
return obj1[key]===obj2[key];
}
});
}
http://jsbin.com/zagecigawi/edit?js
you can use loadash for the same.
using _.isEqual("object1", "object2");
var obj1 = {"prop1" : 2, "prop2" : 3 };
var obj2 = {"prop1" : 2, "prop2" : 3};
console.dir(_.isEqual(obj1, obj2))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Second approach would be
JSON.stringify(obj1) === JSON.stringify(obj2)
This will compare JSON structure of response and model(It will compare keys only and not values & will work for any hierarchy)
function compareObjects(response, model) {
if (response == "" && model == "") {
return false;
}
if (typeof (response) != "object" && typeof (model) != "object") {
var response = JSON.parse(response);
var model = JSON.parse(model);
}
if (typeof (response) != typeof (model)) {
return false;
} else {
switch (Object.prototype.toString.call(model)) {
case '[object]':
var x;
var mKeys = Object.keys(model);
for (x in mKeys) {
return compareObjects(Object.keys(model)[x], Object.keys(response)[x]);
}
break;
case '[object Array]':
return compareObjects(model[0], response[0]);
case "[object String]":
return model == response;
default:
return true;
}
}
}
var response = '[{"educationId":5,"degreeName":"Bacheltecture - B.Arch"},{"educationId":2,"degreeName":"Bachelor of Arts - B.A. "},{"educationId":3,"degreeName":"Bachelor of Ayurvedic Medicine Surgery - B.A.M.S. "}]';
var model = '[{"degreeName":null},{"educationId":null,"degreeName":null},{"educationId":null,"degreeName":null}]';
var output = compareObjects(response, model);
console.log(output);
Two objects in JS even with same properties are never equal. You can stringify objects and compare those strings or iterate over all properties (but it's hard if you need deep compare)
I recommend using a library implementation for Object equality checking. Try the lodash version.
var object = { 'a': 1 };
var other = { 'a': 1 };
_.isEqual(object, other);
// => true

Sort Keys in Javascript Object

I have a Javascript Object that contains a mix of property types including simple strings, objects, arrays of objects... and so on.
I would like to sort the keys following this rule:
'Simple properties like strings or numbers appears always before more complex properties that contains arrays or objects'
I wrote the following function, that almost do what I am trying to achieve, but it converts the arrays into objects. This is not the desired behaviour. Can anybody help me to create a function that keep arrays as arrays and at the same time it sorts the objects inside arrays?
function sort(object){
if (typeof object != "object" )
return object;
var keys = Object.keys(object);
keys.sort(function(a,b){
if (typeof(object[a])!== 'object') { return -1 } else { return 1 }
});
Working jsfiddle:
http://jsfiddle.net/u01mn2py/3/
Kind Regards
As of ECMAScript 2015 (ES6), an object's own properties do have order for some operations, although relying on it is rarely a good idea. If you want order, usually it's best to use an array or similar.
The order is:
Let keys be a new empty List.
For each own property key P of O that is an integer index, in ascending numeric index order
Add P as the last element of keys.
For each own property key P of O that is a String but is not an integer index, in property creation order
Add P as the last element of keys.
For each own property key P of O that is a Symbol, in property creation order
Add P as the last element of keys.
Return keys.
That's for "own" properties. I don't think there are any externally-available operations that define a required order for all properties including inherited ones. (for-in is not required to follow the order above, not even in ES2015+.) As of ES2019, for-in does have a defined order (with some exceptions).
This means that it's probably possible to do what you asked, on a compliant engine, provided none of our keys qualifies as as an integer index.
JSON still has no order, but JSON.stringify is required by the JavaScript spec to use the order described above.
I'm not saying I suggest it. :-)
function sort(object) {
// Don't try to sort things that aren't objects
if (typeof object != "object") {
return object;
}
// Don't sort arrays, but do sort their contents
if (Array.isArray(object)) {
object.forEach(function(entry, index) {
object[index] = sort(entry);
});
return object;
}
// Sort the keys
var keys = Object.keys(object);
keys.sort(function (a, b) {
var atype = typeof object[a],
btype = typeof object[b],
rv;
if (atype !== btype && (atype === "object" || btype === "object")) {
// Non-objects before objects
rv = atype === 'object' ? 1 : -1;
} else {
// Alphabetical within categories
rv = a.localeCompare(b);
}
return rv;
});
// Create new object in the new order, sorting
// its subordinate properties as necessary
var newObject = {};
keys.forEach(function(key) {
newObject[key] = sort(object[key]);
});
return newObject;
}
Live Example (I also updated the fiddle):
function sort(object) {
// Don't try to sort things that aren't objects
if (typeof object != "object") {
return object;
}
// Don't sort arrays, but do sort their contents
if (Array.isArray(object)) {
object.forEach(function(entry, index) {
object[index] = sort(entry);
});
return object;
}
// Sort the keys
var keys = Object.keys(object);
keys.sort(function (a, b) {
var atype = typeof object[a],
btype = typeof object[b],
rv;
if (atype !== btype && (atype === "object" || btype === "object")) {
// Non-objects before objects
rv = atype === 'object' ? 1 : -1;
} else {
// Alphabetical within categories
rv = a.localeCompare(b);
}
return rv;
});
// Create new object in the new order, sorting
// its subordinate properties as necessary
var newObject = {};
keys.forEach(function(key) {
newObject[key] = sort(object[key]);
});
return newObject;
}
var object = {
family: [{
home: {
city: 'Madrid'
},
birth: {
city: 'Madrid'
},
name: 'John',
age: 32
}, {
home: {
city: 'London'
},
birth: {
city: 'Paris'
},
name: 'Marie',
age: 25
}],
name: 'Dani',
age: 33
};
var sortedObject = sort(object);
document.getElementById('container').innerHTML = JSON.stringify(sortedObject, null, '\t');
<pre id="container">
</pre>
(You didn't ask for alphabetical within categories, but it seemed a reasonable thing to throw in.)
That works for me on current Chrome, Firefox, and IE11.
I know I can't relay on javascript properties order, but I need visually to show sorted JSON. Solved in this way:
http://jsfiddle.net/u01mn2py/4/
function sort(object){
if (typeof object != "object" ) // Not to sort the array
return object;
var keys = Object.keys(object);
keys.sort(function(a,b){
if (typeof(object[a])!== 'object') { return -1 } else { return 1 }
});
if( Object.prototype.toString.call( object ) === '[object Array]' ) {
var newObject = [];
} else {
var newObject = {}; }
for (var i = 0; i < keys.length; i++){
newObject[keys[i]] = sort(object[keys[i]])
}
return newObject;
}

Get array of key-values from array of objects without knowing format of array of objects (Javascript)?

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.

Determining if a Javascript object is a "complex" object or just a string

I want to be able to pass either a string literal,
'this is a string'
or a javascript object,
{one: 'this', two: 'is', three: 'a', four: 'string' }
as argument to a function, and take different actions depending on whether it's a string or an object. How do I determine which is true?
To be specific, I want to iterate over the properties of an object, and do some parsing if a property is a string, but nest recursively if the property is an object. I've figured out how to use $.each() to iterate over the properties of the object, but if I just do this with the string, it treates the string as an array of letters rather than as a single thing. Can I get around this some other way?
var data = {
foo: "I'm a string literal",
bar: {
content: "I'm within an object"
}
};
jQuery
$.each(data, function(i, element){
if($.isPlainObject(element){
// we got an object here
}
});
There are similar methods like $.isArray() or $.isFunction() within the jQuery lib.
Native Javascript
for(var element in data){
if(toString.call(element) === '[object Object]'){
// we got an object here
}
}
To use the hack'ish way with toString has the advantage, that you can identify whether it is really an object and an array. Both, objects and arrays would return object by using typeof element.
Long story short, you cannot rely on the typeof operator to distinguish true objects and arrays. For that you need the toString.call(). If you just need to know whether it is any object or not, typeof is just fine.
var a = 'this is a string';
console.log(typeof a); // Displays: "string"
var b = {one: 'this', two: 'is', three: 'a', four: 'string' };
console.log(typeof b); // Displays: "object"
Therefore:
if (typeof yourArgument === 'string') {
// Do the string parsing
}
else if (typeof yourArgument === 'object') {
// Do the property enumeration
}
else {
// Throw exception
}
UPDATE:
Some further considerations:
See #Andy E's comment below.
typeof null returns "object" as well. The same applies to any other object, including arrays.
Try this:
function some_function(argument) {
if (typeof(argument) == "string" || argument.constructor == String) {
// it's a string literal
} else if (argument && typeof(argument) == "object" && argument.constructor != Array) {
// it's an object and not null
} else {
// error
}
}
Thanks to Andy E for the tipp with argument.constructor.
Try the typeof operator. It will return object for objects and string for strings.
you can do something like this
function something(variableX){
if (typeof(variableX) === 'object'){
// Do something
}else if (typeof(variableX) === 'string'){
// Do something
}
}
I was having a similar problem and I think I figured out a solution. Here is my sample code for anyone who is interested.
var propToDotSyntax = function (obj) {
var parse = function (o, n) {
var a = [], t;
for (var p in o) {
if (o.hasOwnProperty(p)) {
t = o[p];
if (n !== undefined) tmp = n + '.' + p;
else tmp = p;
if (t && typeof(t) === 'object') a.push(arguments.callee(t, tmp));
else a.push(tmp + '=' + t);
}
}
return a;
};
return parse(obj).toString();
}
var i = { prop: 'string', obj: { subprop: 'substring', subobj: { subsubprop: 'subsubstring' } } };
propToDotSyntax(i);
This will go through all the properties of an object — even if the properties are objects themselves — and return a string with the following values in dot syntax.
"prop=string,obj.subprop=substring,obj.subobj.subsubprop=subsubstring"
I got the inspiration from DavidPirek.com — Thanks Mr. Pirek!

Categories

Resources