Getting corresponding values from two different objects - javascript

I have returned an object from an ajax call that is the combination of two different arrays' of objects. One is Jobs and the second is the corresponding Customer Records for those jobs. The returned object is formatted like so..
{ "jobs" : [
{jobID: 1,
jobLocation: here
},
{jobID: 2,
jobLocation: there
}
],
"customers" : [
{customerID:1,
customerName:Tom
},
{customerID:2,
customerName:Sally
}
]
}
The items in the job array are sequentially related to the customers in the customer array. (i.e. the first customer owns the first job) How can I iterate or parse then iterate over this object to make list objects<li>'s that have are composed of a field from the jobs array and a field from the corresponding object of the customers array? thank you

A plain, old for-loop might do the job:
var customers = obj.customers;
var jobs = obj.jobs;
var $ul = $("<ul></ul>");
for (var i = 0; i < customers.length; i++) {
var customer = customers[i];
var job = jobs[i];
var $li = $("<li></li>").text(customer.customerName + " - " + job.jobLocation);
$li.appendTo($ul);
}
$("#result").append($ul);
See http://jsfiddle.net/XpQms/

Related

Joining an array on another array's value

I am using mongodb and am building an application with two collections: users and items.
I'd like for users to be able to save items that they like and go to their saved items page where the items would be displayed in the reverse order that they were saved (last saved appears first).
At the moment, I am adding every saved item's id along with the savedDate to the user's profile savedItems array like so:
user profile
{
savedItems: [{id: "", savedDate: ""}, {id: "", savedDate: ""}, etc...]
}
Whenever I need to retrieve those items, I query the items collection for objects with ids $in this array. Like this:
var items = Items.find({_id: {$in: _.pluck(user.savedItems, 'id')}});
The problem here is that I can't order those items according to the addedDate.
So is it possible to map the addedDate onto every object of the retrieved items?
(Something like: if retrievedItems.id == savedItems.id, then push the addedDate there.)
Which would result in an items array like this:
[
{id:"", itemName:"", price: "", [...], savedDate: ""},
{id:"", itemName:"", price: "", [...], savedDate: ""},
[...]
]
Thank you.
JSFIDDLE
I created two function to help you do it:
function mergeDates(listDates, listItems) {
for (var i = 0; i < listDates.length; i++) {
var index = findListIndex(listItems, listDates[i].id);
if (index != null) listItems[index].savedDate = listDates[i].savedDate;
}
return listItems;
}
function findListIndex(listItems, id) {
for (var i = 0; i < listItems.length; i++) {
if (listItems[i].id == id) return i;
}
return null;
}
The first one, mergeDates, takes your first list wich contains the date, the second list, listItems, is the list of your items.
I loop the list with dates, and for each items in it, i call a second function that return the index of the same element in the second list, so findListIndex will search all element and return it's index when he find the same id.
Now the function mergeDates, with the newly found index, will add the value savedDate to your listItems and make it equals to the one on the listDates !
Then the function return the list with all the info of the items, including the dates!
Here is how to call the function:
var listWithDate = mergeDates(savedItems, items);
Hope it helps !

For..In Loop Overwriting ALL Array Values

I'm trying to use a for..in loop to iterate through a list of names, add them to a template object ('group'), then add each complete object to an array ('queryList'). This isn't working because each iteration is overwriting ALL values in the array. Any suggestions why this is happening?
// BATTERY OBJECT
var groupList = [ "LOGIN", "BROWSE", "SEARCH"];
// GROUP OBJECT
var group = {dbName: 'CARS', name: '', collectionName: 'group'};
// INIT VARS
var groupName = '',
queryList = [];
// COMPILATION FUNCTION
var buildGroupQueries = function(group){
// BUILD BATCH OF QUERIES
for (var i in groupList){
groupName = groupList[i];
group.name = groupName;
queryList[i] = group;
}
console.log(queryList);
}
buildGroupQueries(group);
It should look like:
[
{"dbName":"CARS","name":"LOGIN","collectionName":"group"},
{"dbName":"CARS","name":"BROWSE","collectionName":"group"},
{"dbName":"CARS","name":"SEARCH","collectionName":"group"}
]
Instead I'm getting:
[
{"dbName":"CARS","name":"SEARCH","collectionName":"group"},
{"dbName":"CARS","name":"SEARCH","collectionName":"group"},
{"dbName":"CARS","name":"SEARCH","collectionName":"group"}
]
You are creating an array of elements referring to the same object, so they all show the same name coinciding with the last time you changed it, which is "SEARCH" in your example.
You have to refer each element to a new object created from the one you want to use as a template.
To do so you can either loop over its properties or clone it as shown below:
// BATTERY OBJECT
var groupList = [ "LOGIN", "BROWSE", "SEARCH"];
// GROUP OBJECT
var group = {dbName: 'CARS', name: '', collectionName: 'group'};
// INIT VARS
var groupName = '',
queryList = [];
// COMPILATION FUNCTION
var buildGroupQueries = function(group){
var i, _group;
// BUILD BATCH OF QUERIES
for (i in groupList){
_group = JSON.parse(JSON.stringify(group));
groupName = groupList[i];
_group.name = groupName;
queryList[i] = _group;
}
console.log(queryList);
}
buildGroupQueries(group);
You modify the group object each time, but you need to modify its copy.
Add this code just after your line for (var i in groupList){
var _group = {};
for (var j in group){ _group[j] = group[j]; }
On each iteration you create a new object and copy to it all properties from the master object.

Best way to store this data (array, object, etc)

I need to store (many) objects or arrays of data, which need to have the following criteria:
I need to be able to add a new set of data into the existing data easily
I need to be able to sort the data by date/ time added easily (array in order of when entries were pushed to it)
I need to be able to grab an entry easily using a reference, either integer or string. This is important, at the moment I have to do an $.each() to loop through my data until I find the entry I want.
I have tried using a structure like:
saved_info = {
1001: {//all my data for ref 1001},
1002: {//all my data for ref 1002}
}
which gave me what wanted of being able to grab the info easily given a reference:
info = saved_info[1001];
however, the reference numbers I use aren't in order - I use a reference given to me (its a unique identifier), therefore the object isn't in order of when items were added/saved/pushed.
You can use two objects:
One that stores the data by key
Another that stores the sort order
This way you can (i) lookup an element by key (ii) loop over elements in the order they were inserted. Rough outline of the structure:
var DataObject = {
data: {},
sort: []
};
Here is how you add data to this structure:
DataObject.data[1004] = {name: "Test 4"};
DataObject.sort.push(1004);
DataObject.data[1001] = {name: "Test 1"};
DataObject.sort.push(1001);
DataObject.data[1003] = {name: "Test 3"};
DataObject.sort.push(1003);
DataObject.data[1002] = {name: "Test 2"};
DataObject.sort.push(1002);
Here is how you perform a random access:
console.log(DataObject.data[1001].name);
console.log(DataObject.data[1003].name);
And here is how you iterate over all elements in the order they were added:
var i;
for (i = 0; i < DataObject.sort.length; i++) {
console.log(DataObject.data[DataObject.sort[i]].name);
}
It is possible to wrap the entire logic inside a class:
function DataObject() {
this.data = {};
this.sort = [];
this.setItem = function (k, v) {
this.data[k] = v;
this.sort.push(k);
};
this.getItemByKey = function (k) {
return this.data[k];
};
this.getItemByPos = function (i) {
return this.data[this.sort[i]];
};
this.getAllItems = function () {
var i, r = [];
for (i = 0; i < this.sort.length; i++) {
r.push(this.data[this.sort[i]]);
}
return r;
};
}
var t = new DataObject();
t.setItem(1001, {name: "Test 1"});
t.setItem(1002, {name: "Test 2"});
t.setItem(1003, {name: "Test 3"});
t.setItem(1004, {name: "Test 4"});
console.log(t.getItemByKey(1001));
console.log(t.getItemByPos(0));
console.log(t.getAllItems());
Try to build a Json like this,
var xJson = {
"1001":{//all my data for ref 1001},
"1002":{//all my data for ref 1002}
};
and you can fetch the records as per your wish using the bracket notation, since we are using a numeric value as a key.
var xData = xJson["1001"];

js: array with in an associative array

I am trying to set up an associative array for the following data:
name date alpha beta
Andrew 12/08/07 2.3 1.4
5/12/07
26/03/08
____________________________________
Fred 3/09/07 2.1 1.1
23/01/08
____________________________________
Basically, each patient would have a name and alpha , beta value but multiple dates on which they visited doctor. I was thinking of something like following where name is the primary key and dates are stored in an array and alpha, beta is a float value associated with the key.
var info = [{ name: [{ dates: [ ], alpha: float, beta: float }] }];
and then this info array would be populated on reading the csv file. What would be the right format for initialising such an associative array? or what other data structure would be a good approach for representing such a data?
Thanks in advance!
Edit: Since each patient has a unique name, instead of using an array, you should consider using a single object where each patient is an object identified by the object key, for example:
var patientList = {
andy: {},
bob: {}
};
To get your data from your CSV file into this structure you might consider something like this:
var csv = 'Andrew\t12/08/07\t1.2\t3.4\nAndrew\t15/09/08\t1.2\t3.4\nAndrew\t14/08/07\t1.2\t3.4\t\nBob\t18/09/08\t1.2\t3.4\nAndrew\t21/08/07\t1.2\t3.4\nDavid\t31/09/08\t1.2\t3.4\nAndrew\t22/08/07\t1.2\t3.4\t\nSam\t26/09/08\t1.2\t3.4';
// Split the CSV file at the carriage return.
var data = csv.split('\n');
// Recursive over the data with `map`, splitting each line up
// on the tabs and returning a patient object for each.
data = data.map(function (el) {
var patient = el.split('\t');
return {
name: patient[0],
date: patient[1],
alpha: patient[2],
beta: patient[3]
}
});
function getListOfPatientNames(arr) {
var newarr = [];
// For each patient object return the patient name only
newarr = arr.map(function (patient) {
return patient.name;
});
// A quick way of filtering out duplicates
return newarr.filter(function(elem, pos) {
return newarr.indexOf(elem) == pos;
});
}
// Return a unique list of names, and sort them.
var names = getListOfPatientNames(data).sort();
var patientList = {};
for (var i = 0, l = data.length; i < l; i++) {
var name = data[i].name;
// If the patient name doesn't exist in patientList yet
if (!patientList[name]) {
// Add a new patient object using the name as the key
var newPatient = {
dates: [data[i].date],
alpha: data[i].alpha,
beta: data[i].beta
};
patientList[name] = newPatient;
} else {
// If the patient already exists push the date to the dates array
patientList[name].dates.push(data[i].date);
}
}
Demo
The term "associative array" is almost never used wrt JavaScript; you use objects (sometimes called "maps" or "dictionaries") for name/value information, or arrays for ordered data.
It looks like you want an array of patient objects, like this:
var patients = [
{
name: "Andrew",
dates: [/*...the dates...*/],
alpha: 2.3,
beta: 1.4
},
{
name: "Fred",
dates: [/*...the dates...*/],
alpha: 2.1,
beta: 1.1
}
];
You might or might not want to use a constructor function to create those objects, depending on your needs, but with the simple data you've given there's probably no need.

Ordered JSONObject

I have a servlet which talks with the database then returns a list of ordered (ORDER BY time) objects. At the servlet part, I have
//access DB, returns a list of User objects, ordered
ArrayList users = MySQLDatabaseManager.selectUsers();
//construct response
JSONObject jsonResponse = new JSONObject();
int key = 0;
for(User user:users){
log("Retrieve User " + user.toString());
JSONObject jsonObj = new JSONObject();
jsonObj.put("name", user.getName());
jsonObj.put("time", user.getTime());
jsonResponse.put(key, jsonObj);
key++;
}
//write out
out.print(jsonResponse);
From the log I can see that the database returns User objects in the correct order.
At the front-end, I have
success: function(jsonObj){
var json = JSON.parse(jsonObj);
var id = 0;
$.each(json,function(i,item) {
var time = item.time;
var name = item.name;
id++;
$("table#usertable tr:last").after('<tr><td>' + id + '</td><td width="20%">' + time +
'</td><td>' + name +
'</td></tr>');
});
},
But the order is changed.
I only noticed this when the returned list has large size (over 130 users).
I have tried to debug using Firebug, the "response tab" in Firebug shows the order of the list is different with the log in the servlet.
Did i do anything wrong?
EDIT: Example
{"0":{"time":"2011-07-18 18:14:28","email":"xxx#gmail.com","origin":"origin-xxx","source":"xxx","target":"xxx","url":"xxx"},
"1":{"time":"2011-07-18 18:29:16","email":"xxx#gmail.com","origin":"xxx","source":"xxx","target":"xxx","url":"xxx"},
"2":
,...,
"143":{"time":"2011-08-09 09:57:27","email":"xxx#gmail.com","origin":"xxx","source":"xxx","target":"xxx","url":"xxx"}
,...,
"134":{"time":"2011-08-05 06:02:57","email":"xxx#gmail.com","origin":"xxx","source":"xxx","target":"xxx","url":"xxx"}}
As JSON objects do not inherently have an order, you should use an array within your JSON object to ensure order. As an example (based on your code):
jsonObj =
{ items:
[ { name: "Stack", time: "..." },
{ name: "Overflow", time: "..." },
{ name: "Rocks", time: "..." },
... ] };
This structure will ensure that your objects are inserted in the proper sequence.
Based on the JSON you have above, you could place the objects into an array and then sort the array.
var myArray = [];
var resultArray;
for (var j in jsonObj) {
myArray.push(j);
}
myArray = $.sort(myArray, function(a, b) { return parseInt(a) > parseInt(b); });
for (var i = 0; i < myArray.length; i++) {
resultArray.push(jsonObj[myArray[i]]);
}
//resultArray is now the elements in your jsonObj, properly sorted;
But maybe that's more complicated than you are looking for..
As mentioned by ghayes , json objects are unordered.
There are multiple solutions to this problem.
You can use array and the sort it to get the ordered list.
You can use gson library to get the desired order of elements.
I would prefer the second option as it is easy to use.
As JSONObject is order less and internally uses Hashmap. One way to use it to download the all classes from org.json and use in your project directly by changing the internal HashMap implementation to LinkedHashMap in JSONObject.java file. below is the sorted json files
https://github.com/abinash1/Sorted-Json-Object

Categories