1

Consider the following array of objects:

const data = [
   *{...more data from previous dates}*,
   {
     unixDate: 1650348034,  //yesterday
     dateTime: Tue Apr 19 2022 23:00:34,
     severityLevel: 1,
     severity: "Light"
   },
   {
     unixDate: 1650348034,  //yesterday
     dateTime: Tue Apr 19 2022 14:00:34,
     severityLevel: 3,
     severity: "Moderate"
   },
   {
     unixDate: 1650440700,  //today
     dateTime: Wed Apr 20 2022 15:45:00,
     severityLevel: 2,
     severity: "Moderate-Light"
   },
   {
     unixDate: 1650442500,  //today
     dateTime: Wed Apr 20 2022 15:45:00,
     severityLevel: 4,
     severity: "Heavy"
   },
   {
     unixDate: 1650427234,  //today
     dateTime: Wed Apr 20 2022 12:00:00,
     severityLevel: 3,
     severity: "Moderate"
   }

]

I would like to return the following:

{
   *///...records from previous dates,* 
   1650348034 : 2, //yesterday record taking only one of the unixtimestamp, and the average value of 'severityLevel'.
   1650440700 : 3  //same as above but unixtimestamp is today.
}

I'm using the dayjs package to determine whether or not the date is today, via the isToday plugin, but couldn't think of how to compare the dates. The data is growing everyday as it records new readings. I'm not too familiar with the array filter/reduce methods in ES6, would they be useful here? Any help is appreciated!

zer00ne
  • 41,936
  • 6
  • 41
  • 68
Hafiz Hanif
  • 361
  • 1
  • 3
  • 20
  • is the property `dateTime` an actual javascript `Date` object, or a string? At the moment your example object is not valid – Jamiec Apr 20 '22 at 10:28
  • Extract the date from the timestamps (`.map()` + [Unix Timestamp (seconds)](https://day.js.org/docs/en/parse/unix-timestamp)) and then "group" them with: [Counting the occurrences / frequency of array elements](https://stackoverflow.com/questions/5667888/counting-the-occurrences-frequency-of-array-elements) – Andreas Apr 20 '22 at 10:31
  • the property `dateTime` is a valid javascript `Date` object. – Hafiz Hanif Apr 20 '22 at 14:32

5 Answers5

1

First you need to convert those unix times to javascript Date objects. Then you can group by the year/month/date and then average the results.

const data = [   
   {
     unixDate: 1650348034,  //yesterday
     dateTime: "Tue Apr 19 2022 23:00:34",
     severityLevel: 1,
     severity: "Light"
   },
   {
     unixDate: 1650348034,  //yesterday
     dateTime: "Tue Apr 19 2022 14:00:34",
     severityLevel: 3,
     severity: "Moderate"
   },
   {
     unixDate: 1650440700,  //today
     dateTime: "Wed Apr 20 2022 15:45:00",
     severityLevel: 2,
     severity: "Moderate-Light"
   },
   {
     unixDate: 1650442500,  //today
     dateTime: "Wed Apr 20 2022 15:45:00",
     severityLevel: 4,
     severity: "Heavy"
   },
   {
     unixDate: 1650427234,  //today
     dateTime: "Wed Apr 20 2022 12:00:00",
     severityLevel: 3,
     severity: "Moderate"
   }

]

const x = Object.values(data.map(x => ({...x, dateTime: new Date(x.unixDate * 1000)}))
              .reduce( (acc,i) => {
                  const key = "" + i.dateTime.getFullYear() + i.dateTime.getMonth() + i.dateTime.getDate();
                  acc[key] = acc[key] || [];
                  acc[key].push(i);
                  return acc
              },{}))
              .reduce( (obj,rec) => {
                  return {...obj, [rec[0].unixDate]: rec.reduce( (acc,i) => acc+i.severityLevel,0) / rec.length }
              },{})
console.log(x)

Nothe that if the property dateTime is already a javascript date you can do without the data.map(x => ({...x, dateTime: new Date(x.unixDate * 1000)})) part.

Jamiec
  • 133,658
  • 13
  • 134
  • 193
1

Gets a unique list of days and builds an object based on the calculated days

const data = [ { unixDate: 1650348034, dateTime: "Tue Apr 19 2022 23:00:34", severityLevel: 1, severity: "Light" }, { unixDate: 1650348034, dateTime: "Tue Apr 19 2022 14:00:34", severityLevel: 3, severity: "Moderate" }, { unixDate: 1650440700, dateTime: "Wed Apr 20 2022 15:45:00", severityLevel: 2, severity: "Moderate-Light" }, { unixDate: 1650442500, dateTime: "Wed Apr 20 2022 15:45:00", severityLevel: 4, severity: "Heavy" }, { unixDate: 1650427234, dateTime: "Wed Apr 20 2022 12:00:00", severityLevel: 3, severity: "Moderate" } ]

//Get unique list of days
let unique = [... new Set(data.map(d => new Date(d.unixDate * 1000).toLocaleDateString("en-US")))];

//build object based on this list
let results = Object.fromEntries(unique.map(m => {
  let records = data.filter(v => new Date(v.unixDate * 1000).toLocaleDateString("en-US") === m); 
  return [records[0].unixDate, records.reduce((v,o) => v+=o.severityLevel, 0) / records.length ]
}));

console.log(results);
Pellay
  • 792
  • 5
  • 13
1

The method you are looking for is Array.map(), and it's rather easy to use, you call it on an array and provide a function that will return the new data for each index, while the original is provided when to the function it self.

To do what you wish to do tho you also have to use the Object.fromEntries(), to convert the array to an object. Here is how you do it:

let newData = Object.fromEntries(data.map((d)=>[d.unixDate, d.severityLevel]));

This code will first convert your data to an array containing arrays where the 0 index is the key aka time stamp and the 1 index is the data of that key aka your severity level. It will look something like this:

[
  [1650348034,1],
  [1650348034,3],
  [1650440700,2],
  [1650442500,4],
  [1650427234,3]
]

Then it's converted to your object

Look here for more info:

hope this helps

  • Thanks for this explanation. I understand this now. But I'm also looking to concatenate the dates so that there is only one entry per day in the final object. @Pellay's answer wraps it up nicely. – Hafiz Hanif Apr 20 '22 at 14:35
1

Another approach with an util method dayBegins which will calculate the day begin time stamp. This will be useful identify whether timestamps fall into same day or not.

Along with that, just build an tracking object with keys as dayBegin and values with severityLevel and number occurences.

const dayBegins = (uDate) =>
  "" + uDate * 1000 - ((uDate * 1000) % (24 * 60 * 60 * 1000));

const process = (arr, output = {}) => {
  arr.forEach(({ unixDate, severityLevel }) => {
    const key = dayBegins(unixDate);
    if (key in output) {
      output[key].count += 1;
      output[key].sum += severityLevel;
    } else {
      output[key] = {
        unixDate,
        count: 1,
        sum: severityLevel,
      };
    }
  });
  return Object.values(output).reduce(
    (acc, { unixDate, sum, count }) =>
      Object.assign(acc, { [unixDate]: sum / count }),
    {}
  );
};

const data = [
  {
    unixDate: 1650348034, //yesterday
    dateTime: "Tue Apr 19 2022 23:00:34",
    severityLevel: 1,
    severity: "Light",
  },
  {
    unixDate: 1650348034, //yesterday
    dateTime: "Tue Apr 19 2022 14:00:34",
    severityLevel: 3,
    severity: "Moderate",
  },
  {
    unixDate: 1650440700, //today
    dateTime: "Wed Apr 20 2022 15:45:00",
    severityLevel: 2,
    severity: "Moderate-Light",
  },
  {
    unixDate: 1650442500, //today
    dateTime: "Wed Apr 20 2022 15:45:00",
    severityLevel: 4,
    severity: "Heavy",
  },
  {
    unixDate: 1650427234, //today
    dateTime: "Wed Apr 20 2022 12:00:00",
    severityLevel: 3,
    severity: "Moderate",
  },
];

console.log(process(data))
Siva K V
  • 10,561
  • 2
  • 16
  • 29
0

Well, I hope I understood you correctly. This is an example of how you can achieve something similar to your desired output:

//input
const data = [
   {
     "unixDate": 1650348034,  //yesterday
     "dateTime": "Tue Apr 19 2022 23:00:34",
     "severityLevel": 1,
     "severity": "Light"
   },
  {
     unixDate: 1650348034,  //yesterday
     dateTime: "Tue Apr 19 2022 14:00:34",
     severityLevel: 3,
     severity: "Moderate"
   },
   {
     unixDate: 1650440700,  //today
     dateTime: "Wed Apr 20 2022 15:45:00",
     severityLevel: 2,
     severity: "Moderate-Light"
   },
   {
     unixDate: 1650442500,  //today
     dateTime: "Wed Apr 20 2022 15:45:00",
     severityLevel: 4,
     severity: "Heavy"
   },
   {
     unixDate: 1650427234,  //today
     dateTime: "Wed Apr 20 2022 12:00:00",
     severityLevel: 3,
     severity: "Moderate"
   }
];

// ES6 computed property syntax
const arr = data.map(x => { return { [x.unixDate]: x.severityLevel }});

//output
console.log(arr.reduce(function(result, current) {
  return Object.assign(result, current);
}, {}));
Stan
  • 72
  • 5