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) ;
Related
What I would like to do is to process JSON data and store each object after getting out of the for loop. However, the obj gets updated every iteration, so the objectArray holds only David's information in each element in it. I would like the objArray to hold each of the processed JSON objects (screenshot below). The JSON process is to store search a userId and name and store them in the objectArray. Could someone help me figure out how I could store each object in the objectArray? Thank you in advance.
const obj = {};
var objectArray = [];
var data = [
{
"userId": "123",
"name": "John",
"phoneNumber": "123-456-6789"
},
{
"userId": "345",
"name": "Summer",
"phoneNumber": "535-631-9742"
},
{
"userId" : "789",
"name": "David",
"phoneNumber": "633-753-1352"
}
]
var dataLen = data.length;
var people = data;
createKeyValue = ((key, value) => {
var temp = {};
temp["value"] = value;
obj[key] = temp;
});
while (dataLen > 0) {
for (let [key, value] of Object.entries(data[0])) {
switch(key) {
case 'userId':
createKeyValue(key, value);
break;
case 'name':
createKeyValue(key, value);
break;
default:
}
}
objectArray.push(obj);
data.shift();
dataLen -= 1;
}
You can do this using a simple forEach() loop to create and push new objects to the objArray array.
const data = [
{
"userId": "123",
"name": "John",
"phoneNumber": "123-456-6789"
},
{
"userId": "345",
"name": "Summer",
"phoneNumber": "535-631-9742"
},
{
"userId": "789",
"name": "David",
"phoneNumber": "633-753-1352"
}
];
let objArray = [];
data.forEach(person => {
objArray.push({
userId: { value: person.userId },
name: { value: person.name }
});
});
console.log(objArray);
The error you're seeing is because of a concept in JavaScript (and programming in general) known as "passing by reference."
Objects in JS, instead of being passed as whole groups of data, are passed around as addresses to where that data is stored. This saves a lot of overhead, since objects can become quite large.
In your case however, you're running into one of the ways it can trip you up. Since obj is really getting passed by reference instead of value, you're really .pushing 3 copies of the same address (of obj) onto objectArray rather than 3 distinct sets of data.
A better approach to this problem would be using a JS Array function called map(). This function is probably best explained by MDN:
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
You can use it on your data array like this:
var objectArray = [];
var data = [{
"userId": "123",
"name": "John",
"phoneNumber": "123-456-6789"
},
{
"userId": "345",
"name": "Summer",
"phoneNumber": "535-631-9742"
},
{
"userId": "789",
"name": "David",
"phoneNumber": "633-753-1352"
}
]
objectArray = data.map(dataEl => ({
userId: {
value: dataEl.userId,
},
name: {
value: dataEl.name,
},
}));
console.log(objectArray);
.as-console-wrapper {
max-height: 100% !important;
}
As said by our friends Kevin B and Zcoop98, its more appropriate to use forEach function, not map function:
data.forEach(elem => {
objectArray.push({
userId: { value: elem.userId },
name: { value: elem.name }
});
})
I need to access into myObject using a generic function.
Data:
myObject = {
"name": "Caroline",
"number": 32,
"country": {
"province": {
"city": {
"NY": 67989876,
"Boston": 454346,
}
}
}
}
myArray = ["country", "province", "city"]
The solution would be:
myObject["country"]["province"]["city"]
I want rewrite after myObject, then the solution can not be a copy
myObject["country"]["province"]["city"] = "New datas"
var data = myObject;
for (var i in myArray) {
data = data[myArray[i]];
}
alert(data);
Fiddle https://jsfiddle.net/g2uyb8rn/
Shorter version by #JeremyThille is:
var data = myObject;
for (let i of myArray) data = data[i];
alert(data);
I've got an array of three people. I want to add a new key to multiple objects at once based on an array of indices. Clearly my attempt at using multiple indices doesn't work but I can't seem to find the correct approach.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
}
];
array[0,1].title = "Manager";
array[2].title = "Staff";
console.log(array);
Which returns this:
[
{
"name": "Tom",
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
But I'd like it to return this.
[
{
"name": "Tom",
"title": "Manager"
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
You cannot use multiple keys by using any separator in arrays.
Wrong: array[x, y]
Correct: array[x] and array[y]
In your case, it will be array[0].title = array[1].title = "manager";
1st method::
array[0].title = "Manager";
array[1].title = "Manager";
array[2].title = "Staff";
array[0,1] will not work.
2nd method::
for(var i=0;i<array.length;i++) {
var msg = "Manager";
if(i===2) {
msg = "Staff"
}
array[i].title = msg
}
You can use a helper function like this
function setMultiple(array, key, indexes, value)
{
for(i in array.length)
{
if(indexes.indexOf(i)>=0){
array[i][key] = value;
}
}
}
And then
setMultiple(array, "title", [0,1], "Manager");
Try this: `
for (var i=0; var<= array.length; i++){
array[i].title = "manager";
}`
Or you can change it around so var is less than or equal to any n range of keys in the index.
EDIT: instead make var <= 1. The point is to make for loops for the range of indices you want to change the title to.
Assuming that you have a bigger set of array objects.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
},
.
.
.
];
Create an object for the new keys you want to add like so:
let newKeys = {
'Manager': [0,2],
'Staff': [1]
}
Now you can add more such titles here with the required indexes.
with that, you can do something like:
function addCustomProperty(array, newKeys, newProp) {
for (let key in newKeys) {
array.forEach((el, index) => {
if (key.indexOf(index) > -1) { // if the array corresponding to
el[newProp] = key // the key has the current array object
} // index, then add the key to the
}) // object.
}
return array
}
let someVar = addCustomProperty(array, newKeys, 'title')
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]);
};
}
});
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]);