Compare 2 JSON objects [duplicate] - javascript

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Object comparison in JavaScript
Is there any method that takes in 2 JSON objects and compares the 2 to see if any data has changed?
Edit
After reviewing the comments, some clarification is needed.
A JSON object is defined as
"an unordered set of name/value pairs.
An object begins with { (left brace)
and ends with } (right brace). Each
name is followed by : (colon) and the
name/value pairs are separated by ,
(comma)." -- json.org
My goal is to be able to compare 2 JSON object literals, simply put.
I am not a javascript guru so if, in javascript, these are object literals, then I suppose that's what I should call them.
I believe what I am looking for is a method capable of:
Deep recursion to find a unique name/value pair
Determine the length of both object literals, and compare the name/value pairs to see if a discrepancy exists in either.

Simply parsing the JSON and comparing the two objects is not enough because
it wouldn't be the exact same object references (but might be the same values).
You need to do a deep equals.
From http://threebit.net/mail-archive/rails-spinoffs/msg06156.html - which seems the use jQuery.
Object.extend(Object, {
deepEquals: function(o1, o2) {
var k1 = Object.keys(o1).sort();
var k2 = Object.keys(o2).sort();
if (k1.length != k2.length) return false;
return k1.zip(k2, function(keyPair) {
if(typeof o1[keyPair[0]] == typeof o2[keyPair[1]] == "object"){
return deepEquals(o1[keyPair[0]], o2[keyPair[1]])
} else {
return o1[keyPair[0]] == o2[keyPair[1]];
}
}).all();
}
});
Usage:
var anObj = JSON.parse(jsonString1);
var anotherObj= JSON.parse(jsonString2);
if (Object.deepEquals(anObj, anotherObj))
...

Related

Getting an object from n object array if I have one of the keys [duplicate]

This question already has answers here:
Find object by id in an array of JavaScript objects
(36 answers)
Closed 2 years ago.
I have a very complex object that looks like this:
[
{type: "type", data: {a ton more stuff}},
//with tons of these objects.
]
What I am wondering is if all 'type' keys are unique, could I get the object within the array with the given type or will I need to loop through the json array every time?? What I really need is the data, but I only know the type. This is a database schema that is not mine so unfortunately I cannot change the object.
There may be a more efficient way, but you could use Array.prototype.find():
const item = items.find(i => i.type === 'yourType');
You could also loop through once and create a Map if type is unique, using type as the key and the object as the value. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
Short answer is yes. Since it is an array of objects you need to loop through it. What you need is
const newArr = oldArr.filter(obj => (obj.type && obj.type === 'myType' && obj.data) ? obj.data : false));

What is the difference between using a string or a number to index an array in Javascript? [duplicate]

This question already has answers here:
Is a JavaScript array index a string or an integer?
(5 answers)
Closed 4 years ago.
In Javascript it is possible to use a number (integer) or a string (or a char) to index an array for example:
array[0] = true;
or
array['0'] = true;
Does the computer memory work different depending on how you index the array or is it the exact same thing to do it both ways?
The indexes are stored internally as strings.
But it's more common practise to use numbers to access an array by it's index.
A property name P (in the form of a String value) is an array index if
and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not
equal to 2^³²−1
It's explained in this old post
Below is a snippet that showcases it.
Accessing the index with a string works fine as long that index string only contains digits.
But by expressing the index as a word then it can only be accessed with that word. And console logging the array doesn't show it.
let arr = [0,'a one','a two','a three'];
arr['four'] = 'a four';
arr.push('5');
arr.push(6);
arr.push([7,'7']);
arr.push({a:8, b:'8'});
console.log('\nLog the array:\n\n');
console.log(arr);
console.log('\nAccessing the array:\n\n');
console.log("arr[0]:\t" + arr[0]);
console.log("arr[\'1\']:\t" + arr['1']);
console.log("arr[\'two\']:\t" + arr['two']);
let i=2;
console.log("arr[++i]:\t" + arr[++i]);
console.log("arr[\'four\']:\t" + arr['four']);
console.log('arr[4]:\t'+ arr[4]);
console.log('arr[5]:\t'+ arr[5]);
console.log('\nListing the types in the array:\n\n');
for (var a in arr) console.log(a+'\tindex type: '+ typeof a +', value: '+ arr[a] + ', value type: '+ typeof arr[a]);
And here's a snippet to compare speed between using a number or a string in your browser. It should take roughly the same time.
let arr1 = [];
console.time('Access array through string');
for(let i = 0; i <= 42000000;i++){
arr1['42000000'] = 42;
}
console.timeEnd('Access array through string');
let arr2 = [];
console.time('Access array through integer');
for(let i = 0; i <= 42000000;i++){
arr2[42000000] = 42;
}
console.timeEnd('Access array through integer');
The answer is simple: there is no difference.
Javascript arrays are objects. All keys of objects are strings (or symbols), but never numbers.
Property names must be strings. This means that non-string objects
cannot be used as keys in the object. Any non-string object, including
a number, is typecasted into a string via the toString method. ...see more here
The property accessor [] converts to string first before looking for the property. (some engines may optimize this step and not perform a proper toString call, but it's of no concern here)
So array[0] is interpreted as array['0'].
const a = {
toString: function () {
console.log("a.toString called")
return "1";
}
};
const array = ['a','b','c'];
console.log(array[a]);
When you use quotations for indexing, you're creating a key-value pair in the array. I recommended you stick to numerical notation unless you're intentionally creating those pairs; while array['0'] technically posts to the position, it's bad practice.
Even though myArr['two'] doesn't seem to want to show up in the snippet output, if you hit F12 and look at the console output, you'll clearly see it displayed.
["String 0", "String 1", two: "String 2"]
let myArr = [];
myArr[0] = "String 0";
myArr['1'] = "String 1";
myArr['two'] = "String 2";
console.log(myArr);
As the mdn docs state, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
Arrays are actually just objects that have array-like properties. Keys in JavaScript are strings. So when you see an array, it's actually just a set of key-value pairs, where the keys are index numbers.
Arrays are a special data type. Adding keys that do not correlate to possible indexes are added to an 'object property collection' and are not returned when you use the object.
I think the chrome console does the best job of displaying this:
This array is actually an object with keys of 0 1 2 3, a length property, and a prototype.

Javascript list contains a string [duplicate]

This question already has answers here:
Determine whether an array contains a value [duplicate]
(18 answers)
How do I check if an array includes a value in JavaScript?
(60 answers)
Closed 6 years ago.
Does anyone know of a way to check if a list contains a string without using indexOf? In my array some strings can contains parts of others, so indexOf will produce false positives.
As an example, how would I determine if "component" is in the array below?
["component.part", "random-component", "prefix-component-name", "component"]
Update:
It seems like my use of false positive was misleading. I meant that it would say that component was in there 4 times, when I want to match the string by itself.
ie. It should return false when checking for the presence of "component" in the below array.
["component.part", "random-component", "prefix-component-name"]
Use the Array.find API.
Example:
"use strict";
let items = ["component.part", "random-component", "prefix-component-name", "component"];
let found = items.find(item => { return item === "component.part" } );
if (found) {
console.log("Item exists.");
}
For more usage example.
See:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/find
One way is to use .find() to get the string you want from the Array.
Try using $.inArray() method.
var list=["component.part", "random-component", "prefix-component-name", "component"];
if($.inArray(" component",list) != -1){
console.log("Item found");
}
Does anyone know of a way to check if a list contains a string without using indexOf? In my array some strings can contains parts of others, so indexOf will produce false positives.
false positives? Array.prototype.indexOf and Array.prototype.includes both use strict equality which makes that impossible here.
IndexOf won't give you false positive. It will give you 3. If you want to find all elements that has "otherstuff componenet" you can loop through your array and check with String.includes()
Here is a beginner friendly solution.
var arr = ["component.part", "random-component",
"prefix-component-name", "component", "asdf"];
console.log(arr.indexOf('component')); // give u 3
for (var i = 0; i < arr.length; i++){
if (arr[i].includes('component')){
console.log(arr[i]);
}
}

Javascript array [duplicate]

This question already has answers here:
How and why does 'a'['toUpperCase']() in JavaScript work?
(12 answers)
Closed 9 years ago.
Im am working with some code from another developer and came across something I have not seen before. The basic functionality of the code is to look for a piece of data in an object within an object. The object format is theObj {key:Object, key:Object,...}, the data being searched for is stored in 2 variables inkey,lookfor.
$.each(theObj, function(m,n){
if(typeof(n['data'][inkey]) != "undefined" && n['data'][inkey] !== null) {
if(n['data'][inkey][lookfor] == 1){..}
}
});
What does the ['data'] do?
It is looking for a property data in the object n - n['data'] is the same as n.data
n['data'] is the same as n.data but sometime it's useful to use brackets like when you need to use a variable like n['data'][inkey].
Btw you or him should use n.data.hasOwnProperty(inkey) instead of typeof(n['data'][inkey]) != "undefined"
You could write it like that :
$.each(theObj, function(m,n){
if(n.data.hasOwnProperty(inkey) && n.data[inkey] !== null) {
if(n.data[inkey][lookfor] == 1){..}
}
});
data is the property name or key in the object. So n['data'] would return the property value for the property name data in object n.
And what you have is an Object not an Array.
Array contains list of elements with integer based index, where else Object contains list of elements with key based index.

Associative arrays in javascript to JSON

I am using array as an associative array of objects in which keys are ID number of objects in database. Quiet naturally- IDs are large numbers - so that means it is common to have array of length 10^4 with only 20 elements as valid real objects.
I want to send this data back to server but whatever plugins I had to convert js objects to JSON- I tried them all & they all produce a JSON string of length 10^4. So much data can't be sent back.
I need a way of converting associative array to JSON discarding undefined entries.
Any suggestions ?
EDIT:
Example of what my array looks like :
var myAssociativeArray = [undefined, undefined,undefined...., someobject, some other object ...,undefined, ... yet another....]
It sounds like you have a regular array, but you're using it as if it were sparse (which it may or may not be internally). Here's how to use a replacer function that will convert to an object:
JSON.stringify(root, function(k,v)
{
if(v instanceof Array)
{
var o = {};
for(var ind in v)
{
if(v.hasOwnProperty(ind))
{
o[ind] = v[ind];
}
}
return o;
}
return v;
});
Reading your question, it looks are using an array. Here's one solution to get only the defined entries of the array (order not guaranteed).
Note that since it is a sparse array and can go upto 10000 for instance, it's better to only enumerate the properties and not actually loop from 0 to 9999, as most of them will be undefined anyways. So this is better for performance.
var definedEntries = {};
for(var prop in dataObject) {
if(dataObject.hasOwnProperty(prop)) {
definedEntries[prop] = dataObject[prop];
}
}
Then send definedEntries to the server.

Categories

Resources