snippetjavascriptMinor
JavaScript filter() on JSON object?
Viewed 0 times
javascriptobjectfilterjson
Problem
I'm building a web interface for a home monitoring sensor array, and fetching JSON from the backend framework. I want to start putting statistics together for monitoring different areas of the home, inside and outside.
Each thermal sensor provide the reading, in regular intervals, of temperature and time of day, so I end up with a JSON object looking like this:
and so on, with multiple sensors each displaying pretty large JSON objects for the reporting periods.
I want to derive the highest and lowest temperatures around the house, and at what time they occurred, using JavaScript (with AngularJS). Currently, I'm looking to optimize this (which does work):
```
/* The entire array of data, within time frame set by the user
* and for the sensors defined by the user
* from the RESTful API (params)
*/
api.sensor_data.get(params, function(data){
$scope.sensorStats = {
"kitchen" : {},
"garage" : {}
}
/ find the highest temperature for a single sensor /
let hightemp_kitchen = Math.max.apply(Math, data.sensor_1.temp_f.map(function(t){
retu
Each thermal sensor provide the reading, in regular intervals, of temperature and time of day, so I end up with a JSON object looking like this:
{
"sensor_1" : [
{
"location" : "garage_east",
"temp_f" : [{
"value" : "71.2",
"timestamp" : "2017-05-01T08:15:00"
},
{
"value" : "70.8",
"timestamp" : "2017-05-01T08:30:00"
},
{
"value" : "72.6",
"timestamp" : "2017-05-01T08:45:00"
}
]}],
"sensor_2" : [{
"location" : "kitchen",
"temp_f" : [{
"value" : "78.2",
"timestamp" : "2017-05-01T08:15:00"
},
{
"value" : "78.8",
"timestamp" : "2017-05-01T08:30:00"
},
{
"value" : "78.6",
"timestamp" : "2017-05-01T08:45:00"
}]
}]}and so on, with multiple sensors each displaying pretty large JSON objects for the reporting periods.
I want to derive the highest and lowest temperatures around the house, and at what time they occurred, using JavaScript (with AngularJS). Currently, I'm looking to optimize this (which does work):
```
/* The entire array of data, within time frame set by the user
* and for the sensors defined by the user
* from the RESTful API (params)
*/
api.sensor_data.get(params, function(data){
$scope.sensorStats = {
"kitchen" : {},
"garage" : {}
}
/ find the highest temperature for a single sensor /
let hightemp_kitchen = Math.max.apply(Math, data.sensor_1.temp_f.map(function(t){
retu
Solution
It seems like you should not be hard-coding concepts such as "kitchen", "garage", etc. into your code at all. You need to design that out.
Also I question the JSON structure.
But let's assume you can't do that, and think of ways we can get you the information make this whole thing more dynamic. I am not sure what
Based on your comment regarding
Also I question the JSON structure.
sensor_* are meaningless property names, giving you an unnecessary level of nesting, so if you have control over JSON generation, you might consider an array of object like:[
{
"location": ...,
"temp_f": [
...
]
},
{
...
}
]But let's assume you can't do that, and think of ways we can get you the information make this whole thing more dynamic. I am not sure what
params is even used for, so I am discarding this.api.sensor_data.get(function(data){
let sensorData = {};
// loop through each sensoer object, ignore top level key value
Object.values(data).forEach( (sensor) => {
// reduce f_temp array to single entry with highest temp
// and set to sensorData result object with location as key
sensorData[sensor.location] = sensor.f_temp.reduce( (acc, metric) => {
if(parseFloat(metric.value) > parseFloat(acc.value)) acc = metric;
return acc;
}, sensor.f_temp[0]);
});
$scope.sensorStats = sensorData;
}Based on your comment regarding
params, you might have something more like this:let sensorData = {};
let sensors = Object.values(data);
// filter by location
if (location in params) {
sensors = sensors.filter( (sensor) => sensor.location === params.location );
}
// loop through each sensor objects
sensors.forEach( (sensor) => {
let result = null;
let metrics = sensor.f_temp;
if(minTimestamp in params) {
metrics = metrics.filter( metric => {
return (Date.parse(metric.timestamp) >= params.minTimeStamp );
});
}
if(maxTimestamp in params) {
metrics = metrics.filter( metric => {
return (Date.parse(metric.timestamp) = 0) {
result = metrics.reduce( (acc, metric) => {
if(parseFloat(metric.value) > parseFloat(acc.value)) acc = metric;
return acc;
}, metrics[0]);
sensorData[sensor.location] = result;
});
$scope.sensorStats = sensorData;
}Code Snippets
[
{
"location": ...,
"temp_f": [
...
]
},
{
...
}
]api.sensor_data.get(function(data){
let sensorData = {};
// loop through each sensoer object, ignore top level key value
Object.values(data).forEach( (sensor) => {
// reduce f_temp array to single entry with highest temp
// and set to sensorData result object with location as key
sensorData[sensor.location] = sensor.f_temp.reduce( (acc, metric) => {
if(parseFloat(metric.value) > parseFloat(acc.value)) acc = metric;
return acc;
}, sensor.f_temp[0]);
});
$scope.sensorStats = sensorData;
}let sensorData = {};
let sensors = Object.values(data);
// filter by location
if (location in params) {
sensors = sensors.filter( (sensor) => sensor.location === params.location );
}
// loop through each sensor objects
sensors.forEach( (sensor) => {
let result = null;
let metrics = sensor.f_temp;
if(minTimestamp in params) {
metrics = metrics.filter( metric => {
return (Date.parse(metric.timestamp) >= params.minTimeStamp );
});
}
if(maxTimestamp in params) {
metrics = metrics.filter( metric => {
return (Date.parse(metric.timestamp) =< params.maxTimeStamp );
});
}
if(metrics.length > 0) {
result = metrics.reduce( (acc, metric) => {
if(parseFloat(metric.value) > parseFloat(acc.value)) acc = metric;
return acc;
}, metrics[0]);
sensorData[sensor.location] = result;
});
$scope.sensorStats = sensorData;
}Context
StackExchange Code Review Q#162633, answer score: 2
Revisions (0)
No revisions yet.