how to construct a json object using info from several javascript arrays - javascript

I have two js arrays already, say: names and values (with the same length), now I would like to construct a json object in certain format? For example:
names = ["label1","label2","label3"];
values = [[[0,1],[1,9],[2,10]],[[0,89],[1,91],[2,1]],[[0,1],[1,9],[2,10]]];
I would like to have a json array data_spec in this format:
[{
label:"label1",
data:[[0,1],[1,9],[2,10]]
},
{
label:"label2",
data:[[0,89],[1,91],[2,1]]
},
{
label:"label3",
data:[[0,1],[1,9],[2,10]]
}]
Could anyone tell one how? Thanks a lot!

For a bit of variety and a check,
var data_spec = [];
if (names.length != values.length) {
// panic, throw an exception, log an error or just return an empty array
} else {
for (var i=0, name; name = names[i]; i++) { // assuming a non-sparse array
data_spec[i] = {
label : name,
data : values[i]
};
}
}
That is, non-sparse and not containing anything else that would evaluate to false.
If your framework has an each function added to Array and you don't care about performance,
var data_spec = [];
names.each(function(name) {
data_spec.push({ label : name, data : values[names.indexOf(name)] });
});
If your framework is a clean one like Dojo and puts it somewhere else (ex is Dojo),
var data_spec = [];
dojo.forEach(names, function(name) {
data_spec.push({ label : name, data : values[names.indexOf(name)] });
});
If your framework has an each function that returns an Array of identical length with the results of every operation at their expected position,
var data_spec = arrayOfResultsEach(names, function(name) {
return { label : name, data : values[names.indexOf(name)] };
});
These are just for illustration, indexOf inside loops of arbitrary length is a major code smell.

Just use a loop (make sure the two arrays are of same length)
result = [];
for(var i=0, len=names.length; i < len; i++) {
result.push({label: names[i], data: values[i]});
}

var myArray =
[{
"label": "label1",
"data" :
{
"0": "1",
"1": "9",
"2": "10"
}
},
{
"label": "label2",
"data" :
{
"0": "89",
"1": "91",
"2": "1"
}
},
{
"label": "label3",
"data" :
{
"0": "1",
"1": "9",
"2": "10"
}
}];
alert(myArray[0].data[2]);

Related

JavaScript - Processing and restructuring JSON not working

I'm trying to process a json file and create a new one, but it does not work.
The structure of an old json is something like this:
[
{
"3":{
"value":2
},
"4":{
"value":1
}
},
{
"3":{
"value":6
},
"4":{
"value":1
}
}...and so on
What I'm trying to do is to create a new json object, which will have only two objects 0 and 1 and inside each of them there will be values from indexes 3 and 4 from the old one, which should look something like this:
{
"0":{
"0":[
{
"0":2
}
],
"1":[
{
"0":6
}
]..and so on
},
"1":{
"0":[
{
"0":1
}
],
"1":[
{
"0":1
}
]..and so on
}
}
The problem is that when I process and cook the old json the output for both indexes(0,1) is the same. I'm trying to loop it through 3 and 4 and assign those values into the new array but something is not quite right.
Fraction of the code:
//loop through the keysIndex
for (var c in keysIndex) {
//the new json has to be 2 objects, hence the below
newData[c] = {};
var vallueArr = [];
var newObj = {
0: oldData[i][keysIndex[c]].value
}
vallueArr.push(newObj);
objInNewData[entries] = vallueArr;
//the problem is somehwere here, it is appending twice the same
//objInNewData and not both 3 and 4 individually
newData[c] = objInNewData;
}
Hers's the whole logic: PLUNKER
Can someone please help as I cannot get my head around this :(
Many thanks
As I mentioned above, the use of index of keys of objects is not a good idea, because objects in Javascript have no defined order. For ordered items I suggest to use an array instead.
var data = [
{
"3": { "value": 2 },
"4": { "value": 1 }
}, {
"3": { "value": 6 },
"4": { "value": 1 }
}
],
keys = Object.keys(data[0]), // <-- ATTENTION!
obj = {};
data.forEach(function (a, i) {
keys.forEach(function (k, j) {
obj[j] = obj[j] || {};
obj[j][i] = obj[j][i] || [];
obj[j][i].push({ '0': a[k].value });
});
});
document.write('<pre>' + JSON.stringify(obj, 0, 4) + '</pre>');

Working with JSON Javascript

I have a set of JSON object in a text file called text.json which looks like the following:
{
"school": [
{
"student": {
"name": "John",
"lastname": "Ghram",
"studentId": "000111"
}
},
{
"student": {
"name": "Harry",
"lastname": "Smith",
"studentId": "000112"
}
},
{
"teacher": {
"name": "Teacher One",
"teacherId": 1001
}
}
]
}
The following code is use to read from file
var obj = (function () {
var json = null;
$.ajax({
'async': false,
'global': true,
'url': "text.json",
'dataType': "json",
'Content-type': 'application/json',
'success': function (data) {
obj = data;
}
});
return obj;
})();
When the obj is returned to get the name of student name I am using
obj.school[0].student['name'].
is there a way to store all student information as one JSON object called students and the teacher to other called teachers, so I can access the info without using the index number. For Eg: student.name.
No, this is exactly what arrays are for. You cannot store multiple instances of the name property on one object, that makes no sense. How would student.name possibly resolve to a single name, if student represented multiple students?
I've formatted your json and then applied a for loop to find object keys that match 'student' and then augmented the students object with the name.
If two names are the same, they'll be overwritten, so this isn't the best approach:
var obj = {
"school": [
{"student": { "name":"John", "lastname": "Ghram", "studentId": 000111 }},
{"student": { "name": "Harry","lastname": "Smith", "studentId": 000112 }},
{"teacher": { "name": "Teacher One", "teacherId": 1001 }}
]
};
var i, arr = obj.school, len = arr.length;
var students = Object.create(null);
for(i=0; i<len; i++) {
if(Object.keys(arr[i])[0] === 'student') students[arr[i].student.name] = arr[i];
}
Can now use square-bracket notation:
students['John'], students['Harry'], etc
You just need to new an array to store them, you can write a function like this
function getStudents(obj)
{
var res = new Array() ;
var school = obj['school'] ;
for(item in school)
{
for(q in school[item])
{
if(q=="student")//you can change it to "teacher"
{
res.push(school[item]) ;
}
}
}
console.log(res) ;
return res ;//return an array(object) of students;
}
getStudents(obj) ;

JSON data transformation from table-like format to JSON?

I have data that's in this format:
{
"columns": [
{
"values": [
{
"data": [
"Project Name",
"Owner",
"Creation Date",
"Completed Tasks"
]
}
]
}
],
"rows": [
{
"values": [
{
"data": [
"My Project 1",
"Franklin",
"7/1/2015",
"387"
]
}
]
},
{
"values": [
{
"data": [
"My Project 2",
"Beth",
"7/12/2015",
"402"
]
}
]
}
]
}
Is there some super short/easy way I can format it like so:
{
"projects": [
{
"projectName": "My Project 1",
"owner": "Franklin",
"creationDate": "7/1/2015",
"completedTasks": "387"
},
{
"projectName": "My Project 2",
"owner": "Beth",
"creationDate": "7/12/2015",
"completedTasks": "402"
}
]
}
I've already got the column name translation code:
r = s.replace(/\%/g, 'Perc')
.replace(/^[0-9A-Z]/g, function (x) {
return x.toLowerCase();
}).replace(/[\(\)\s]/g, '');
Before I dive into this with a bunch of forEach loops, I was wondering if there was a super quick way to transform this. I'm open to using libraries such as Underscore.
function translate(str) {
return str.replace(/\%/g, 'Perc')
.replace(/^[0-9A-Z]/g, function (x) {
return x.toLowerCase();
})
.replace(/[\(\)\s]/g, '');
}
function newFormat(obj) {
// grab the column names
var colNames = obj.columns[0].values[0].data;
// create a new temporary array
var out = [];
var rows = obj.rows;
// loop over the rows
rows.forEach(function (row) {
var record = row.values[0].data;
// create a new object, loop over the existing array elements
// and add them to the object using the column names as keys
var newRec = {};
for (var i = 0, l = record.length; i < l; i++) {
newRec[translate(colNames[i])] = record[i];
}
// push the new object to the array
out.push(newRec);
});
// return the final object
return { projects: out };
}
DEMO
There is no easy way, and this is really not that complex of an operation, even using for loops. I don't know why you would want to use regex to do this.
I would start with reading out the column values into a numerically indexed array.
So something like:
var sourceData = JSON.parse(yourJSONstring);
var columns = sourceData.columns[0].values[0].data;
Now you have a convenient way to start building your desired object. You can use the columns array created above to provide property key labels in your final object.
var sourceRows = sourceData.rows;
var finalData = {
"projects": []
};
// iterate through rows and write to object
for (i = 0; i < sourceRows.length; i++) {
var sourceRow = sourceRows[i].values.data;
// load data from row in finalData object
for (j = 0; j < sourceRow.length; j++) {
finalData.projects[i][columns[j]] = sourceRow[j];
}
}
That should do the trick for you.

Get an object in array by one of its fields

Sorry I'm kind of new to JS; I have an array of object; how can I get the name of the object which has the key "user_key3" and obviously without having a loop and have a condition.
arr = [{
"name": "user1",
"key": "user_key1"
},{
"name": "user3",
"key": "user_key3"
},{
"name": "user2",
"key": "user_key2"
}]
Please let me know if you need more clarification
Thanks
You can do it the functional way, like this
var name;
arr.forEach(function(currentObject) {
if (currentObject.key === "user_key3") {
name = currentObject.name;
}
});
If you want to short-circuit on the first match, you can use Array.prototype.some, like this
var name;
arr.some(function(currentObject) {
if (currentObject.key === "user_key3") {
name = currentObject.name;
return true;
}
return false;
});
The OP had mentioned obviously without having a loop and have a condition. I would do it as below:
arr = [{
"name": "user1",
"key": "user_key1"
},{
"name": "user3",
"key": "user_key3"
},{
"name": "user2",
"key": "user_key2"
}];
var keyValMap = arr.map(function(n) { return n.key } );
var arrIndex = keyValMap.indexOf('user_key3');
alert(arr[arrIndex].name);
Fiddle
You'll have to iterate and check for the key
var user_name;
for (var i=0; i<arr.length; i++) {
if ( arr[i].key === 'user_key3' ) {
user_name = arr[i].name;
break;
}
}
FIDDLE
You've edited the question to include
obviously without having a loop and have a condition
but a loop and a condition is by far the most efficient and cross-browser way to do this, so why would you "obviously" not want this ?
An inefficient yet concise solution would be
var keyarr = arr.map(function(x) { return x.key } );
//keyarr is list of keys
var index=keyarr.indexOf("user_key3");
//arr[index] is your answer. Index will be -1 if the key doesn't exist
In general, finding an item that satisfies some arbitrary property in an array requires you to loop over the array:
function find(arr, name) {
for (var i=0; i<arr.length; i++) {
if ( arr[i].key === name ) {
return arr[i];
}
}
}
Then to find it,
var obj = find(arr, 'user_key3');
Using more functional solutions to find the item is fine too, but you still end up looping in some way.
However, if you are doing lookups by key, then an array of key-value pairs is not the best data structure. I would suggest using an object directly:
var map = {
'user_key1': 'user1',
'user_key2': 'user2',
'user_key3': 'user3'
}
Then lookup is simply:
map['user_key3'];
Try this - underscore.js
For Your Example -
_.where(arr, {key: "user_key3"});
You cannot do such thing with Objects in Javascript. Though here you have a combination of callbacks and loop:
arr = [{
"name": "user1",
"key": "user_key1"
},{
"name": "user3",
"key": "user_key3"
},{
"name": "user2",
"key": "user_key2"
}];
arr.forEach(function(elme){
for(var g in elme)
{
if(elme[g] == 'user_key3')
{
console.log("Found the value: "+g+" : "+elme[g]);
};
}
});

How can I access the name of the fields of a json array inside a for loop?

My Json array looks like this:
var data =
{
"categories":
{
"category1":
{
"Name": "Maps",
"Id": 3,
"orderInList": 1
},
"category2":
{
"Name": "Books",
"Id": 2,
"orderInList": 2
}
}
};
When I write do console.log(data), the 'key' to the object is formatted like:
| key | value |
categories[category1][Id] "3"
How can I iterate over this in a for loop (without using JQuery's $.each) so I can tell which key, value pairs are Names, Id's or orderInList's?
Working Jsfiddle
Something like this should work:
for (var category in data['categories']) {
for (var key in data['categories'][category]) {
var value = data['categories'][category][key];
// Now do whatever you want based on key...
switch (key) {
case 'Name':
// Whatever
break;
default:
break;
}
}
}
In any case, key and value in the inner loop will hold the key and value of your nested object, and category will hold the category.
The potentially confusing thing about this is that object properties can be accessed like array values in Javascript.
So consider the code below:
var some_object = {
a: 0
};
// These two lines do the same thing, even though some_object is not an array.
some_object.a = 1;
some_object['a'] = 1;
Your outer categories object is an object that contains many child objects. You can iterate through these children objects using a for...in loop.
for (var category in data.categories) {
// here you can access `category.Name`, `.Id`, and `.orderInList`
}
Checkout this
var data = {
"categories": {
"category1": {
"Name": "Maps",
"Id": 3,
"orderInList": 1
},
"category2": {
"Name": "Books",
"Id": 2,
"orderInList": 2
}
}
};
function represent(obj) {
var reprs = [];
for (var key in obj) {
if(!obj.hasOwnProperty(key)) continue;
if (obj[key] instanceof Object) {
var result = represent(obj[key]);
for (var i = 0; i < result.length; i++) {
reprs.push("[" + key + "]" + result[i]);
}
}
else {
reprs.push("[" + key + "] = " + obj[key]);
}
}
return reprs;
}
console.log(represent(data));
//output
["[categories][category1][Name] = Maps",
"[categories][category1][Id] = 3",
"[categories][category1][orderInList] = 1",
"[categories][category2][Name] = Books",
"[categories][category2][Id] = 2",
"[categories][category2][orderInList] = 2"]
which key, value pairs are Names, Id's or orderInList's?
I think you can add code at the recursion terminate condition to check if the key is equal to Names Id or orderInList

Categories