Matching 2 JSON objects - javascript

I have a very large json like :
raw_obj= {"001" : {....}, "002" : {....}};
and I have an another json object which is just returned from server :
search_result = {["001", "005", "123"]};
I want to do something like
$.each(search_result, function(i,val){
alert(raw_obj.search_result[i]);
});
Is it possible? I don't want to loop through those 2 objects because in practical, there will be have around 2000 elements in a "raw_json". Which means the worst case is 2000x2000 times loop per one query.

var raw_obj= {"001" : {'...'}, "002" : {'...'}};
var search_results = ["001", "005", "123"]; // just an array
$.each(search_results, function(i, result) {
alert(raw_obj[result]);
});
The search results are an array (ie, list), not an object (ie, map) and so the syntax should be modified as above. If you have no control over the server response, use string parsing to build a new array.

Related

revise deeply nested JSON array in DOM

I have an HTML page that contains a stringified JSON object. The object has this structure:
{
"x":{
"key1":[],
"key2":{},
"keyN":{},
"myKey":{
"randomID238492":{
"items":[
{ "value":"zzzz" },
{ "value":"aaaa" },
{ ...}
]
}
}
}
}
I want to replace this object with one in which the "items" array has been sorted. Here is what I will and won't know about the object:
"myKey" and "items" will always be the relevant object keys
"myKey" will contain only one random ID, and the "items" key will always be its first child
I won't know the order of "myKey" in the object.
I won't know the true randomID under which "items" nests.
Is there a clear, efficient way to replace this JSON object with one in which "items" has been sorted? Right now, I do it by using this jQuery function after the page has rendered:
$(function() {
var myData = $( "#myJSON_string" )[0]; // <script> node that contains the string
var myDataJSON = JSON.parse(myData.innerText); // JSON string
var myKeyJSON = myDataJSON["x"]["myKey"]; // object
var myArr = myKeyJSON[Object.keys(myKeyJSON)[0]]["items"]; // array to sort
// Now sort and revise. I'm leaving myCompare() out of the example for brevity
myKeyJSON[Object.keys(myKeyJSON)[0]]["items"] = myArr.sort(myCompare);
myDataJSON["x"]["myKey"] = myKeyJSON;
myDataJSON = JSON.stringify(myDataJSON);
myData.innerText = myDataJSON;
});
This approach works, but it seems rather labored. It might be better, for example, if I could revise the JSON object "in place" without parsing it and then re-stringifying it.
Many SO posts, like this one, speak to the general question of how to sort a JSON array. But I can't see that any speak to the specific question posed here.

Append data acquired from JSON to a Raphael object

Solved the question on my own, see answer
Using jQuery 3.2.1 and Raphael 2.1.1, if this matters
In my Raphael .js I first create some objects without any data and push them into an array, e. g. (.attr omitted):
var objarr = [];
var obj1 = rsr.path("M ... z");
objarr.push(obj1);
After this, I want to take data from a JSON file (an array named "regions" of multiple entries that consist of multiple key-value pairs (validated through JSONLint) and append it as data by id. It looks like this:
{
"regions": [{
"id": "0",
"var1": "foo1",
"var2": "bar1",
},
{
"id": "1",
"var1": "foo2",
"var2": "bar2",
},
// And so on for every object
]
}
I use the following code (localhost is used because otherwise I get a cross-access error:
for (var i = 0; i < objarr.length; i++)
{
var jq = $.getJSON("http://localhost:8000/data.json",{id: +i},function(t){
console.log( "success" );
})
.done(function(objdata){
console.log("success2");
$.each(objdata.regions, function(key, val){
objarr[i].data(key,val);
});
})
.fail(function(t){
console.log("error");
})
.always(function(t){
console.log("complete");
});
}
The console gives me both successes, but after this I get an error "Cannot read property 'data' of undefined". alert(key) and alert(val) give 0 and [object Object] respectively for every call. I tried adding the following to .done:
var items = [];
$.each(objdata.regions, function(key, val){
items.push("id" + key + ":" + val);
console.log(items);
});
The result was a string that went ["id0:[object Object]"],["id0:[object Object]", "id1:[object Object]"] and so on until it had objarr.length ids, repeating the needed amount of times. If I add [i] to objdata.regions, I get no console messages about items[] content at all.
I also found two somewhat closely related questions ("1" and "2"), checked the jQuery documentation for .getJSON(); and Raphael documentation for Element.data();. I've tried the following to check validity of my calls:
console.log(objdata) in the beginning of .done -- returns full base object of JSON data
console.log(objdata.regions) in the beginning of .done -- returns array of objects of JSON data
console.log(objdata.regions[i]) in the beginning of .done -- returns undefined
console.log(objdata.regions[0]) in the beginning of .done -- returns first object (works for every object)
I've used objdata.regions[0] in the snippet with items[] and the adding seems to work properly (console shows the keys and values being added to the array). However, it still doesn't work with objarr[i].data(key,val) (as well as ""+key and "$key").
I have two questions:
1. How do I acquire the key-value pairs properly while looping?
2. How do I append these pairs as data to a Raphael object?
I moved the for loop inside .done() and everything is appended successfully:
.done(function(objdata){
for (var i = 0; i < objarr.length; i++)
{
console.log("success2");
$.each(objdata.regions[i],function(key, val){
objarr[i].data(key, val);
});
}
})

merge object with nested properties in JavaScript

I want to merge two object using JavaScript
First
{
"user" : " Hari",
"friend" : "Shiva",
"friendList": ["Hanks"," Tom"," Karma"," Hari"," Dinesh"]
}
second
{
"user" : "Hari",
"friend" : " Shiva",
"friendList" : ["Karma"," Tom"," Ram"," Bindu"," Shiva",
" Kishna"," Bikash"," Bakshi"," Dinesh"]
}
and form a single object:
expected output
{
"user" : "Hari"
"friend" : "Shiva",
"friendList":[
["Hanks"," Tom","Karma"," Hari"," Dinesh"],
["Karma"," Tom"," Ram"," Bindu"," Shiva"," Kishna"," Bikash"," Bakshi"," Dinesh"]
]
}
Is it possible? I am sorry if it is wrong question....but I need to solve in this way and I do not have much idea about JavaScript.
You can add from one array to anther like this
var a={
"user" : " Hari",
"friend" : "Shiva",
"friendList": ["Hanks"," Tom"," Karma"," Hari"," Dinesh"]
};
var b={
"user" : "Hari",
"friend" : " Shiva",
"friendList" : ["Karma"," Tom"," Ram"," Bindu"," Shiva",
" Kishna"," Bikash"," Bakshi"," Dinesh"]
};
b.friendList.concat(a.friendList);
you will get on b all the array of a+b...
you will not get this structure that you want. For my code you will get an array of strings from a and b, if you want this structure you need to change the result to be an object and not array.
also can see example from : link
The following code will merge the objects as described in your question:
var firstObject = {
"user" : " Hari",
"friend" : "Shiva",
"friendList": ["Hanks"," Tom"," Karma"," Hari"," Dinesh"]
};
var secondObject = {
"user" : "Hari",
"friend" : " Shiva",
"friendList" : ["Karma"," Tom"," Ram"," Bindu"," Shiva",
" Kishna"," Bikash"," Bakshi"," Dinesh"],
};
function mergeMyObjectsIntoNew(first,second,copyFriendListArrayReference){
//.trim() is needed in the compare here because example data has a leading space
// in secondObject.friend
if(first.user.trim() === second.user.trim()
&& first.friend.trim() === second.friend.trim()){
var newObject={}; //The new object
newObject.user = first.user;
newObject.friend = first.friend;
newObject.friendList = []; //Create new array
if(copyFriendListArrayReference){
//This copies references for the arrays in first.friendList and
// second.friendList into the array new.friendList. These will be the
// same arrays as exists in first and second. Changes to the contents
// of those arrays will affect the arrays in the newObject.
newObject.friendList[0] = first.friendList; //add friendList from first
newObject.friendList[1] = second.friendList; //add friendList from second
}else{
//This copies the string contents of the arrays in first.friendList and
// second.friendList into the array new.friendList. These will NOT be the
// same arrays as exists in first and second. Changes to the contents
// of those arrays will NOT affect the arrays in the newObject.
// This is the default behavior.
//Copy contents of friendList from first
newObject.friendList[0] = Array.from(first.friendList);
//Copy contents of friendList from second
newObject.friendList[1] = Array.from(second.friendList);
}
return newObject;
}//implicit else due to 'return' in all if paths
return null; //Indicate to caller that there was not a match.
}
//Get new merged object with copy of friendList
mergedObject = mergeMyObjectsIntoNew(firstObject,secondObject);
console.log(mergedObject);
Comments
Using multiple very similarly structured objects is, often, a bad idea
It is, generally, not a good idea to use objects that have two different structures, unless you are keeping those objects distinctly separate. When you do have multiple structures for objects which you treat similarly (i.e. you use the same functions/methods to manipulate objects with both structures), all of your code has to account for each of the multiple structures. This can rapidly make your code much more complex and, potentially, more confusing than it would need to be if you did not have multiple structures for objects which you treat similarly.
In this case, you are wanting your result object to have a friendList property which is an array of arrays of strings whereas your source objects have a friendList property which is an array of strings. If you are going to use mergeMyObjectsIntoNew on both object structures, having the two different structures for the friendList property would require more logic in mergeMyObjectsIntoNew, if you want it to be able to operate on both types of object with the results you would, probably, expect.
For instance, the following code will not produce the result that you are probably expecting:
mergedFirstSecondObject = mergeMyObjectsIntoNew(firstObject,secondObject);
mergedthirdFourthObject = mergeMyObjectsIntoNew(firstObject,secondObject);
mergedFourObjects = mergeMyObjectsIntoNew(mergedFirstSecondObject,mergedthirdFourthObject);
This will produce an object that has a friendList property that is an array of arrays of arrays of strings. The mergedFourObjects object is structured like:
{
"user" : " Hari",
"friend" : "Shiva",
"friendList": [
[
friendListArrayFromFirstObject,
friendListArrayFromSecondObject
],
[
friendListArrayFromThirdObject,
friendListArrayFromFourthObject
]
]
}
In your case, you are probably better off picking to always have the friendList property be only one or the other of an array of array of strings, or an array of strings. Having the friendList property such that it might be either structure will significantly complicate your code everywhere you use these objects.
Using a class would be the better approach to handling your objects
If you are going to be using your objects in a larger project, it is probably a better idea to use a class for the object. This would allow you to move things like comparing the objects and merging the objects into methods of the class (e.g. MyObject.prototype.compare(second) and MyObject.prototype.merge(second). However, that is a discussion well beyond the scope of your question. If you want more information, I suggest you search for information about using object classes in JavaScript.

Javascript map CSV string to JSON array

this one baffles me and I'm not even sure I'm searching the correct keywords for possible explanations.
I am sending an RPC to a remote server. The response I get is just a comma-delimited string with values (no keys) like so:
val1,val2,val3,val4,val5,val6,val7,val8,val9
When I receive this response I need to map these values through JS to keys (hard-coded, I designate) and generate a JSON array like this:
{
"response": {
"mykey1" : "val1",
"mykey2" : "val2",
"mykey3" : "val3",
"mykey4" : "val4",
"mykey5" : "val5",
"mykey6" : "val6",
"mykey7" : "val7",
"mykey8" : "val8",
"mykey9" : "val9"
}
}
Can anybody nudge me in the right direction...sample code or tutorials that are close to what I am looking for? This is a for middleware script that gets called when server receives the response.
This is my first post here, been looking a long time learning and applying in Obj-C and as I am learning Swift, but JS is new to me. I apologize in advance if I am breaking any protocols by asking for help without posting my feeble attempts at figuring this out...
You can split the response on comma, which will give you an array.
Since both arrays (keys and vals) are the same length, you can loop over either and create your array of objects that way. See below
var response = 'val1,val2,val3,val4,val5';
var keys = [
'key1', 'key2', 'key3', 'key4', 'key5'
];
var dict = [];
var vals = response.split(',');
vals.forEach(function(val, i) {
dict[keys[i]] = val;
});
console.log(dict);
Read my comment, then check this out:
var result = 'val1,val2,val3,val4,val5,val6,val7,val8,val9';
// real question should be why result is not JSON already
var resArray = result.split(',');
console.log(resArray[0]); // first result
console.log(resArray[1]); // second result

Change the name of keys while creating an array

I have the response in the following format after doing groupby in solr query. I am using solr version 3.5
"grouped":{
"channel_id":{
"matches":48,
"ngroups":26,
"groups":[{
"groupValue":"204",
"doclist":{"numFound":1,"start":0,"docs":[
{
"channel_name":"ZeeTv",
"channel_num":4,
"title":"The Name",
"channel_id":"204"
}},
{
"groupValue":"166",
"doclist":{"numFound":2,"start":0,"docs":[
{
"channel_name":"Sony",
"channel_num":2,
"title":"The Name",
"channel_id":"166",
{
"channel_name":"Sony",
"channel_num":2,
"title":"The Puzzle",
"channel_id":"166"
}}]}}
I am taking the response in an array in the following way :
for(var chl in data.grouped.channel_id.groups) {
config['playlist'].push(data.grouped.channel_id.groups[chl]['doclist']['docs']);
}
Thus an individual array of each groupValue is formed. The struture of the array is:
"0"=>{"0"=>"value"},"1"=>{"0"=>"result1","1"=>"result2"}
But i want to change the key name i.e. "0","1" to the groupValue from the response while creating an array so that i can do config['playlist']['166'] to check all the shows for this channel_id from the array. Can this be done and if so how. I am expecting the following :
"204"=>{"0"=>"value"},"166"=>{"0"=>"result1","1"=>"result2"}
Also if possible can the solr query be made such that the channel_num in the response comes in ascending order i.e. first result for channel_num 2 and then 4. I have done groupby:channel_id
What about that?
for(var chl in data.grouped.channel_id.groups) {
config['playlist'][data.grouped.channel_id.groups[chl].groupValue] = data.grouped.channel_id.groups[chl]['doclist']['docs'];
}
Push is there to add an element at the end of an array. But any Javascript object is just a hash table, so you can use it that way.
By the way, you can make the code simpler with a for each :
for each(var chl in data.grouped.channel_id.groups) {
config['playlist'][ch1.groupValue] = ch1['doclist']['docs'];
}
Pikrass has answered correctly... as far as ordering with channel_num is concerned try adding the following in your query:
&sort=channel_num asc

Categories