HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavascriptMinor

JavaScript filter() on JSON object?

Submitted by: @import:stackexchange-codereview··
0
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:

{
"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. 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.