I have a survey system using Angular and Firebase which stores the results of users answers inside of an object specific to each user. This works well for storing data, but I've realized that it may be difficult to pull the data back out due to each object having a unique name.
I'd like to loop over each object and pull the all of the values together. So for all 50 entries find the total of comprehension.icons.damage[1]
How can I construct a loop that goes over objects with unique names like the objects below?
Here is my json structure
"usersanonymous:-JgTyGt6An3WWyLvnnuu" : {
"comprehension" : {
"-JgTzC0r_H58n7y8Al_-" : {
"date" : 1422154060632,
"icons" : [ {
"damage" : [ null, "0", "3", "3" ],
"ocular" : [ null, "2", "3", "1" ],
"physical therapy" : [ null, "0", "4", "4" ],
"skin" : [ null, "4", "0", "1" ]
} ]
}
}
},
"usersanonymous:-JgU-ryIpI-HR7D4VDkp" : {
"comprehension" : {
"-JgU0MwBwisNbjvRFGOT" : {
"date" : 1422154629142,
"icons" : [ {
"damage" : [ null, "0", "3", "4" ],
"ocular" : [ null, "1", "4", "3" ],
"physical therapy" : [ null, "2", "4", "3" ],
"skin" : [ null, "4", "1", "3" ]
} ]
}
}
}
Given your input data, I would create a function to extract just the data you're interested in. I've written this in raw javascript - if you're using jQuery you may have fun using $.map rather than for (x in y).
var data = {
"usersanonymous:-JgTyGt6An3WWyLvnnuu": {
"comprehension": {
"-JgTzC0r_H58n7y8Al_-": {
"date": 1422154060632,
"icons": [{
"damage": [null, "0", "3", "3"],
"ocular": [null, "2", "3", "1"],
"physical therapy": [null, "0", "4", "4"],
"skin": [null, "4", "0", "1"]
}]
}
}
},
"usersanonymous:-JgU-ryIpI-HR7D4VDkp": {
"comprehension": {
"-JgU0MwBwisNbjvRFGOT": {
"date": 1422154629142,
"icons": [{
"damage": [null, "0", "3", "4"],
"ocular": [null, "1", "4", "3"],
"physical therapy": [null, "2", "4", "3"],
"skin": [null, "4", "1", "3"]
}]
}
}
}
};
function extractComprehension(rawData) {
var result = [];
for (var usersanonymous in rawData) {
usersanonymous = rawData[usersanonymous];
if (usersanonymous.comprehension) {
for (var token in usersanonymous.comprehension) {
token = usersanonymous.comprehension[token];
if (token.icons) {
result.push(token.icons[0]);
}
}
}
}
return result;
}
function sumOf(objectList, property, index) {
var result = 0;
for (var o in objectList) {
var numbers = (objectList[o][property] || []);
if (numbers.length >= index) {
result += parseInt(numbers[index], 10);
}
}
return result;
}
Using this mini api you can get the sum of the properties you're interested in:
// Get the data array.
var comprehension = extractComprehension(data);
// Sum some property.
console.log(sumOf(comprehension, 'damage', 3));
Related
So I am trying to merge 2 arrays of objects by ID-s (ID and AUTOMOBIL) with this code I only push last array of objects(OPREMA). Someone have any idea how can I get all of them in the spot they should be?
So when ID in a1 is == 1 I need all of OPREMA in a2 witch AUTOMOBIL is equal to 1 to save it together it a1, but with this code it's only saving last one.
const a1 = [
{ ID: "2", TIP: "A3", VRSTA: "Limousine", $$hashKey: "object:3" },
{ ID: "1", TIP: "A5", VRSTA: "Coupe", $$hashKey: "object:7" },
];
const a2 = [
{
AUTOMOBIL: "1",
OPREMA: {
ID: "5",
NAZIV_OPREME: "Automatski",
VRSTA_OPREME: "2",
CIJENA: "15000",
OPIS: "Automatski mjenjač",
},
},
{
AUTOMOBIL: "1",
OPREMA: {
ID: "3",
NAZIV_OPREME: "Benzin",
VRSTA_OPREME: "1",
CIJENA: "7000",
OPIS: "Gorivo benzin",
},
},
{
AUTOMOBIL: "1",
OPREMA: {
ID: "19",
NAZIV_OPREME: "1.0",
VRSTA_OPREME: "5",
CIJENA: "7000",
OPIS: "potrosnja 3-6l",
},
},
{
AUTOMOBIL: "1",
OPREMA: {
ID: "11",
NAZIV_OPREME: "Sportback",
VRSTA_OPREME: "3",
CIJENA: "70000",
OPIS: "sportski izgled šasije",
},
},
{
AUTOMOBIL: "1",
OPREMA: {
ID: "8",
NAZIV_OPREME: "Quattro",
VRSTA_OPREME: "4",
CIJENA: "15000",
OPIS: "Pogon na sve kotače",
},
},
];
const a3 = a1.map(t1 => ({ ...t1, ...a2.find(t2 => t2.AUTOMOBIL === t1.ID) }));
//RESULT OF a3
console.log(a3);
In your question you never specified how exactly you want the elements of a2 to be saved in the a1 element. I'm assuming that you need them as a array under the OPREMA property. Your code was pretty close but instead of find you needed to use filter to keep all elements that match.
const a3 = a1.map(t1 => {
const matchingElements = a2.filter(t2 => t2.AUTOMOBIL === t1.ID);
return ({...t1, OPREMA: matchingElements.map(({ OPREMA }) => OPREMA) });
});
var params1 = {
spreadsheetId: '1g9y32IkyujOupw6O6eRhtlCcwhn5vv9mM_Yr4peRRmo',
range: str,
};
var clearValuesRequestBody = {
};
var request = await gapi.client.sheets.spreadsheets.values.clear(params1, clearValuesRequestBody);
Above code is to delete a row from the google sheet. Now, my question is that how to remove that blank row from the google sheet by moving rest of the rows?
Answer:
You need to use a batchUpdate to do this.
Request Example:
{
"requests": [
{
"deleteDimension": {
"range": {
"sheetId": sheetId,
"dimension": "ROWS",
"startIndex": 0,
"endIndex": 1
}
}
}
]
}
The above request will delete the first row from a sheet with given gid.
The rows are 0-indexed so starting at 0 and ending at 1 will delete the first row. Likewise, starting at 8 and ending at 18 will delete rows 9-18.
The method is as follows:
gapi.client.sheets.spreadsheets.batchUpdate(resource)
Note: This is spreadsheets.batchUpdate and NOT spreadsheets.values.batchUpdate.
All together now:
const resource = {
"requests": [
{
"deleteDimension": {
"range": {
"sheetId": sheetId,
"dimension": "ROWS",
"startIndex": 0,
"endIndex": 1
}
}
}
]
}
const response = gapi.client.sheets.spreadsheets.batchUpdate({
"spreadsheetId": "your-spreadsheet-id",
"resource": resource
})
.then(function(response) {
console.log("Response is: \n", response)
}, function(err) {
console.error("Execute error", err)
})
In order to get which rows are blank, you will have to use spreadsheets.values.get and manually loop through the response.
The response will be of the following form; you will need to loop through response.values:
{
"range": "Sheet1!A1:Z1000",
"majorDimension": "ROWS",
"values": [
[] // each row is an array
]
}
In this example I am using a Spreadsheet that looks like this:
For this spreadsheet, response will be:
{
"range": "Sheet1!A1:Z1000",
"majorDimension": "ROWS",
"values": [
[ "1", "1", "1", "1", "1", "1", "1", "1", "1", "1" ],
[ "2", "2", "2", "2", "2", "2", "2", "2", "2", "2" ],
[ "3", "3", "3", "3", "3", "3", "3", "3", "3", "3" ],
[ "4", "4", "4", "4", "4", "4", "4", "4", "4", "4" ],
[],
[ "6", "6", "6", "6", "6", "6", "6", "6", "6", "6" ],
[],
[],
[ "9", "9", "9", "9", "9", "9", "9", "9", "9", "9" ],
[ "10", "10", "10", "10", "10", "10", "10", "10", "10", "10" ],
]
}
so we just need to check what elements of response.result.values are empty arrays:
Assume that the Spreadsheet has columns up to ZZZ so to encapulate the whole range, you can make the request:
const emptyRows = []
gapi.client.sheets.spreadsheets.values.get({
"spreadsheetId": "your-spreadsheet-id",
"range": "A:ZZZ"
})
.then(function(response) {
response.result.values.forEach(function(row, index) {
if (row.length == 0) emptyRows.push(index)
})
}, function(err) {
console.error("Execute error", err)
})
and then loop through this array backwards, passing the values into the previous batchUpdate request to completely remove them from the sheet. It's important delete from bottom up so to not change row numbers and accidentally delete rows with data in them.
Note: this will not delete empty rows past the last data row, only empty rows within the data set.
References:
Method spreadsheets.batchUpdate | Sheets API | Google Developers
Row and Column Operations | Sheets API | Google Developers
Method: spreadsheets.values.get | Sheets API | Google Developers
I have an array of objects. i want to filter array based the object has the condition.
my array is as follow :
var data = [
{
"name": "nitin",
"r_id": "1",
"t_id": "4"
},
{
"name": "test",
"r_id": "2",
"t_id": "3"
},
{
"name": "test1",
"r_id": "2",
"t_id": "4"
},
{
"name": "test3",
"r_id": "3",
"t_id": "3"
},
{
"name": "test2",
"r_id": "1",
"t_id": "1"
}]
and my object is as follows :
var obj = {
role:['1','2'],
type:['1','3']
}
where r_id is the role id and t_id is the type id
so i want the results whose role id is in 1 or 2 AND type id is in 1 or 3.
so mathematically role_id && type_id ((1||2)&&(1||3))
my output should like:
var result = [
{
'name':'test',
'r_id':2,
't_id':3,
},
{
'name':'test2',
'r_id':1,
't_id':1,
}];
var data = [
{
"name": "nitin",
"r_id": "1",
"t_id": "4"
},
{
"name": "test",
"r_id": "2",
"t_id": "3"
},
{
"name": "test1",
"r_id": "2",
"t_id": "4"
},
{
"name": "test3",
"r_id": "3",
"t_id": "3"
},
{
"name": "test2",
"r_id": "1",
"t_id": "1"
}]
var obj = {
role:['1','2'],
type:['1','3']
}
let result = data.filter(item=>{
return obj.role.indexOf(item.r_id) > -1 && obj.type.indexOf(item.t_id) > -1
})
console.log(result)
var data = [
{
"name": "nitin",
"r_id": "1",
"t_id": "4"
},
{
"name": "test",
"r_id": "2",
"t_id": "3"
},
{
"name": "test1",
"r_id": "2",
"t_id": "4"
},
{
"name": "test3",
"r_id": "3",
"t_id": "3"
},
{
"name": "test2",
"r_id": "1",
"t_id": "1"
}]
var obj = {
role:['1','2'],
type:['1','3']
}
var filterItems = data.filter(function(o){
return obj.role.indexOf(o.r_id) != -1 && obj.type.indexOf(o.t_id) != -1; });
console.log(filterItems);
You could change obj a bit, for corresponding property names in the data, you have, then use Array#filter and check with Array#every for wanted item.
var data = [{ name: "nitin", r_id: "1", t_id: "4" }, { name: "test", r_id: "2", t_id: "3" }, { name: "test1", r_id: "2", t_id: "4" }, { name: "test3", r_id: "3", t_id: "3" }, { name: "test2", r_id: "1", t_id: "1" }],
obj = { r_id: ['1', '2'], t_id: ['1', '3'] },
keys = Object.keys(obj),
result = data.filter(function (o) {
return keys.every(function (k) {
return obj[k].indexOf(o[k]) !== -1;
});
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You just need to iterate your data and see if the keys (r_id and t_id) are present in the obj (in the respective arrays). For this you can use Array.filter
var data = [{"name":"nitin","r_id":"1","t_id":"4"},{"name":"test","r_id":"2","t_id":"3"},{"name":"test1","r_id":"2","t_id":"4"},{"name":"test3","r_id":"3","t_id":"3"},{"name":"test2","r_id":"1","t_id":"1"}]
var obj = {
role:['1','2'],
type:['1','3']
}
var result = data.filter(function(element){
return obj.role.indexOf(element.r_id) !== -1 && // element has valid role
obj.type.indexOf(element.t_id) !== -1 // element has valid type
})
console.log(result)
I am trying to merge two json array with objects as element. You may refer to this plunkr file for both json. I have succesfully retrieve the expected final outcome array id, but I do not know how to form back the expected json as below. I am using underscore js for this purpose.
Note: If object exist in newJson and not in currentJson, after merge, it will be inactive state by default.
I am not sure whether I am using the correct approach. This is what I have try:
var newJsonID = _.pluck(newJson, 'id');
var currentJsonID = _.pluck(currentJson, 'id');
var union = _.union(newJsonID, currentJsonID);
var intersection = _.intersection(currentJsonID, newJsonID);
var final = _.difference(union, _.difference( currentJsonID, intersection);
Expected Final Outcome:
[
{
"id": "12",
"property1Name": "1"
"status": "inactive"
},
{
"id": "11",
"property1Name": "1"
"status": "inactive"
},
{
"id": "10",
"property1Name": "1"
"status": "inactive"
},
{
"id": "9",
"property1Name": "1"
"status": "active"
}
]
A solution in plain Javascript with two loops and a hash table for lookup.
function update(newArray, currentArray) {
var hash = Object.create(null);
currentArray.forEach(function (a) {
hash[a.id] = a.status;
});
newArray.forEach(function (a) {
a.status = hash[a.id] || 'inactive';
});
}
var newJson = [{ "id": "12", "property1Name": "1" }, { "id": "11", "property1Name": "1" }, { "id": "10", "property1Name": "1" }, { "id": "9", "property1Name": "1" }],
currentJson = [{ "id": "10", "property1Name": "1", "status": "inactive" }, { "id": "9", "property1Name": "1", "status": "active" }, { "id": "8", "property1Name": "1", "status": "active" }, { "id": "7", "property1Name": "1", "status": "inactive" }];
update(newJson, currentJson);
document.write('<pre>' + JSON.stringify(newJson, 0, 4) + '</pre>');
I always think it's going to be easy... I plan to use the json below to build router objects. I put a console.log and so I could have a break point spot so I could try to figure out how to access the the object properties from the chrome console. It never goes into the for loop though.
The main question is how to properly turn the JSON into objects and how to access it's properties.
<script type="text/javascript">
$(document).ready(function(){
$.getJSON('JSON/data.json', function(json) {
for (var i=0;i<json.length;i++){
console.log("in for loop");
}
});
});
</script>
{
"_id": {
"$oid": "4f91f2c9e4b0d0a881cf86c4"
},
"DSC21": {
"Router": {
"online": [
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1"
],
"bytes": [
"59.5721304971465",
"17014.1911069063",
"14858.8518936735",
"6875.20981475265",
"15157.6891384625",
"6363.47544785913",
"29446.2111270486",
"11517.9296243171",
"27077.9747917112",
"19867.79381695"
]
}
},
"DSC22": {
"Router": {
"online": [
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1"
],
"bytes": [
"59.5721304971465",
"17014.1911069063",
"14858.8518936735",
"6875.20981475265",
"15157.6891384625",
"6363.47544785913",
"29446.2111270486",
"11517.9296243171",
"27077.9747917112",
"19867.79381695"
]
}
},
"DSC23": {
"Router": {
"online": [
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1"
],
"bytes": [
"59.5721304971465",
"17014.1911069063",
"14858.8518936735",
"6875.20981475265",
"15157.6891384625",
"6363.47544785913",
"29446.2111270486",
"11517.9296243171",
"27077.9747917112",
"19867.79381695"
]
}
},
"DSC24": {
"Router": {
"online": [
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1",
"1"
],
"bytes": [
"59.5721304971465",
"17014.1911069063",
"14858.8518936735",
"6875.20981475265",
"15157.6891384625",
"6363.47544785913",
"29446.2111270486",
"11517.9296243171",
"27077.9747917112",
"19867.79381695"
]
}
}
}
The variable json is already an object, but it is not an array, so a typical for-loop is insufficient. Since json.length is undefined, i<json.length fails on the first iteration and you skip over the loop.
for (var key in json) {
// key is your DSCxxx
// json[key] is the corresponding object
}
JSON is natively available in JavaScript, you traverse it like you would traverse any object or array.
json["DSC21"]["Router"]["online"][0]; // 1
json.DSC21.Router.online[0]; // equivalent
json.DSC21.Router.online.0; // INCORRECT
If you don't know the names of the properties and want to loop through them use the for .. in construction:
for (var key in json) {
console.log(key); // _id, DSC21, DCS22 etc..
console.log(json[key]); // { "$oid": "" }, { "Router": ".." } etc.
}
This does leave the hasOwnProperty issue, but it shouldn't be a problem if you're just reading JSON data.
maybe you want to know how to iterate your objects?
here would be how to do that:
for( var key in json ){
if( key != '_id'){
var router = json[key].Router;
for( var i = 0; i < router.online.length; i++ ){
console.log(i + ' is online: ', router.online[i]==1?'true':'false');
}
etc...
}
}