Filter/Reduce 根据日期将对象数组转换为新对象

Filter/Reduce array of objects into a new object based on day

考虑以下对象数组:

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"
   }

]

我想return以下内容:

{
   *///...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.
}

我正在使用 dayjs 包通过 isToday 插件来确定日期是否是今天,但想不出如何比较日期。 data 每天都在增长,因为它记录了新的读数。我不太熟悉 ES6 中的数组 filter/reduce 方法,它们在这里有用吗?感谢您的帮助!

首先你需要将这些 un​​ix 时间转换为 javascript Date 对象。然后您可以按 year/month/date 分组,然后对结果进行平均。

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)

请注意,如果 属性 dateTime 已经是 javascript 日期,您可以不使用 data.map(x => ({...x, dateTime: new Date(x.unixDate * 1000)})) 部分。

获取唯一的天数列表并根据计算出的天数构建对象

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);

您正在寻找的方法是Array.map(),它很容易使用,您在数组上调用它并提供一个函数,该函数将为每个索引return 新数据, 而原文是提供当它自己的功能时。

要完成您想做的事,您还必须使用 Object.fromEntries() 将数组转换为对象。以下是您的操作方法:

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

此代码将首先将您的数据转换为包含数组的数组,其中 0 索引是键也就是时间戳,1 索引是该键的数据也就是您的严重级别。它看起来像这样:

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

然后转换为你的对象

查看此处了解更多信息:

希望这对您有所帮助

好吧,我希望我理解正确。这是一个示例,说明如何实现与所需输出类似的结果:

//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);
}, {}));

另一种使用 util 方法的方法 dayBegins 将计算日期开始时间戳。这将有助于确定时间戳是否属于同一天。

除此之外,只需构建一个跟踪对象,其键为 dayBegin,值具有 severityLevel 和出现次数。

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))