Home > Blockchain >  How to loop for a specific key for the number of times it occurs in an array of objects
How to loop for a specific key for the number of times it occurs in an array of objects

Time:01-08

I'm currently working on an iot project which needs to calculate the average of a 15 minute window starting from :-

| Blocks         | Average               |
| 00:00 - 00:15  | average of this block |
| 00:15 - 00:30  | average of this block |
| 00:30 - 00:45  | average of this block |
| 00:45 - 01:00  | average of this block |

and so on.I've implemented one solution. The flow goes in this manner.

iot core -> rules engine -> sqs queue -> lambda function (triggered by cloudwatch cron job which runs it every 15th minute of the hour)

The lambda code I've is to count the number of distinct sites (devices) in the payload and calculate occurences for each of the site(devices) as i have to calculate average in time block fashion for multiple sites or devices Here is my test event which i have configured for now to test the function :-

[
  {
    "site_name": "adodar",
    "active-power": 23.4
  },
  {
    "site_name": "adodar",
    "active-power": 10.4
  },
  {
    "site_name": "adodar",
    "active-power": 2.4
  },
  {
    "site_name": "adodar",
    "active-power": 3.4
  },
  {
    "site_name": "adodar",
    "active-power": 11.4
  },
  {
    "site_name": "adodar",
    "active-power": 0.4
  },
  {
    "site_name": "jamanvada",
    "active-power": 6.4
  },
  {
    "site_name": "jamanvada",
    "active-power": 0.5
  },
  {
    "site_name": "jamanvada",
    "active-power": 4.55
  },
  {
    "site_name": "abcd",
    "active-power": 9.08
  }
]

Here is my lambda code to count the number of occurence for each site:-

export const handler = async(event) => {
    // TODO implement
    let occurences = {};
    let arr = event;
    arr.map( data => {
      occurences[data.site_name]=(occurences[data.site_name] || 0) 1;
    });
    console.log(occurences);
};

Here i get the correct output as expected to count the number of records for each device or site, here is my output:-

 { adodar: 6, jamanvada: 3, abcd: 1 }

Now I want to loop for each site or device for as many times as the number of occurences and calculate the average for that. For instance, device adaodar has 6 occurences so formula is

add all 6 occurences / number of occurences for each site.

For instance adodar has 6 instaces i want to loop over those 6 objects and calculate the average of "active-power" field.

But i'm unable to achieve this.

Any help would be greatly appreciated.

CodePudding user response:

You should be able to calculate the averages by storing the active-power sum and count for each site:

export const handler = async (event) => {
  let occurences = {};
  event.forEach(data => {
    if (occurences[data.site_name] === undefined) {
      occurences[data.site_name] = {
        activePowerSum: 0.0,
        count: 0
      };
    }
    occurences[data.site_name].activePowerSum  = data['active-power'];
    occurences[data.site_name].count  ;
  });
  let averages = {};
  for (const key in occurences) {
    averages[key] = occurences[key].activePowerSum / occurences[key].count;
  }
  console.log(occurences, averages);
};

CodePudding user response:

I have took occurences and iterate through each value in array using map and divide the sum of values by his length:

> siteValues = {}
> Object.keys(occurences).forEach(key => { siteValues[key] = array.filter(x=>x.site_name==key).map(value => value['active-power'])});
undefined
> siteValues
{
  adodar: [ 23.4, 10.4, 2.4, 3.4, 11.4, 0.4 ],
  jamanvada: [ 6.4, 0.5, 4.55 ],
  abcd: [ 9.08 ]
}

to get the sum of each site name i have used reduce and divide between array length using again array.filter (maybe have some extra calulation operations):

> Object.keys(occurences).forEach(key => { siteValues[key] = array.filter(x=>x.site_name==key).map(value => value['active-power']).reduce(function(a, b) { return a   b; }, 0) / array.filter(x=>x.site_name==key).length});
undefined
> siteValues
{
  adodar: 8.566666666666665,
  jamanvada: 3.8166666666666664,
  abcd: 9.08
}

which is equivalent to: { adodar: 51.39999999999999 / 6, jamanvada: 11.45 / 3, abcd: 9.08 / 1 }

  • Related