1

我有按天分组的日期数组,我想按时间开始和结束对日期进行分组,然后减去最后一个值 - 第一个值。

时间开始和结束也在一个数组中。

数据数组:

const data = [
  { x: "2021-10-17T24:00:00.000Z", y: 52 },
  { x: "2021-10-17T22:14:00.000Z", y: 44 },
  { x: "2021-10-17T22:10:00.000Z", y: 36 },
  { x: "2021-10-17T22:00:00.000Z", y: 29 },
  { x: "2021-10-17T20:14:45.540Z", y: 24 },
  { x: "2021-10-17T20:13:45.540Z", y: 20 },
  { x: "2021-10-17T20:00:45.540Z", y: 18 },
  { x: "2021-10-17T14:38:45.540Z", y: 17 },
  { x: "2021-10-17T13:38:45.540Z", y: 15 },
  { x: "2021-09-16T14:36:46.540Z", y: 13 },
  { x: "2021-01-04T14:35:46.540Z", y: 12 },
  { x: "2021-01-01T14:30:46.540Z", y: 10 },
  { x: "2020-02-01T06:28:47.520Z", y: 7 },
  { x: "2020-02-01T07:28:47.520Z", y: 6 },
  { x: "2019-04-13T10:19:20.034Z", y: 5 },
  { x: "2018-01-01T09:09:19.134Z", y: 4 },
  { x: "2017-01-01T12:09:19.034Z", y: 3 },
  { x: "2016-01-02T12:10:20.034Z", y: 2 },
  { x: "2016-01-02T11:10:20.034Z", y: 1 }
];

时间开始和结束数组:

const configurations = [
  {
    label: "C1",
    startTime: { hr: "06", min: "00" },
    endTime: { hr: "22", min: "00" }
  },
  {
    label: "C2",
    startTime: { hr: "22", min: "00" },
    endTime: { hr: "24", min: "00" }
  }
];

按天分组的数据:

[
  {
    "value": 37, // 52 -15 (last value - first value)
    "label": "2021/10/17",
    // (I want to group this data by time start and end)
    "data": [
      {
        "x": "2021-10-17T13:38:45.540Z",
        "y": 15
      },
      {
        "x": "2021-10-17T14:38:45.540Z",
        "y": 17
      },
      {
        "x": "2021-10-17T20:00:45.540Z",
        "y": 18
      },
      {
        "x": "2021-10-17T20:13:45.540Z",
        "y": 20
      },
      {
        "x": "2021-10-17T20:14:45.540Z",
        "y": 24
      },
      {
        "x": "2021-10-17T22:00:00.000Z",
        "y": 29
      },
      {
        "x": "2021-10-17T22:10:00.000Z",
        "y": 36
      },
      {
        "x": "2021-10-17T22:14:00.000Z",
        "y": 44
      },
      {
        "x": "2021-10-17T24:00:00.000Z",
        "y": 52
      }
    ]
  },
//...
]

预期输出:

[
  {
    "value": 37, // 52 -15 (last value - first value)
    "label": "2021/10/17",
    "data": [
              {
                value: 14, // 29-15 =14
                label: "C1"
              },
              {
                value: 23, // 52-29 = 23
                label: "C2"
              }
            ]
  },
 // ...
]

这就是我尝试的 Group data by time start 和 end

4

1 回答 1

2

我没有通过你的所有脚本遵循逻辑。我将在以下内容中对此进行评论:

parseInt(item.startTime.hr, 10) * 60

parseInt是多余的,因为乘法会将字符串强制为数字。

我已将输入数据修改为使用 Date 对象而不是时间戳,并且所有计算都使用 UTC。

以下首先生成日期分组数据,然后处理配置数据。如果组中只有一天,则值为 0,因为它是第一个也是最后一个条目。如果没有适合配置类别的日期,则该值为空,因此不会添加到结果数据中。

forEach循环之一可以转换为reduce,但有时forEach在逻辑上更容易理解。:-)

希望评论是足够的,请询问您是否需要澄清。

let data = [
  { x: new Date('2021-10-17T23:59:59.999Z'), y: 52 },
  { x: new Date('2021-10-17T22:14:00.000Z'), y: 44 },
  { x: new Date('2021-10-17T22:10:00.000Z'), y: 36 },
  { x: new Date('2021-10-17T22:00:00.000Z'), y: 29 },
  { x: new Date('2021-10-17T20:14:45.540Z'), y: 24 },
  { x: new Date('2021-10-17T20:13:45.540Z'), y: 20 },
  { x: new Date('2021-10-17T20:00:45.540Z'), y: 18 },
  { x: new Date('2021-10-17T14:38:45.540Z'), y: 17 },
  { x: new Date('2021-10-17T13:38:45.540Z'), y: 15 },
  { x: new Date('2021-09-16T14:36:46.540Z'), y: 13 },
  { x: new Date('2021-01-04T14:35:46.540Z'), y: 12 },
  { x: new Date('2021-01-01T14:30:46.540Z'), y: 10 },
  { x: new Date('2020-02-01T06:28:47.520Z'), y: 7 },
  { x: new Date('2020-02-01T07:28:47.520Z'), y: 6 },
  { x: new Date('2019-04-13T10:19:20.034Z'), y: 5 },
  { x: new Date('2018-01-01T09:09:19.134Z'), y: 4 },
  { x: new Date('2017-01-01T12:09:19.034Z'), y: 3 },
  { x: new Date('2016-01-02T12:10:20.034Z'), y: 2 },
  { x: new Date('2016-01-02T11:10:20.034Z'), y: 1 }
];

let configurations = [
  {
    label: "C1",
    startTime: { hr: "06", min: "00" },
    endTime: { hr: "22", min: "00" }
  },
  {
    label: "C2",
    startTime: { hr: "22", min: "00" },
    endTime: { hr: "24", min: "00" }
  }
];

function groupByDay(data) {
  // Used in reduce
  let currentDate, group;
  // Group by day
  let dayGroups = data.reduce((acc, item) => {
    // Get the date
    let date = item.x.toISOString().substring(0,10);
    // If a new date, start a new group
    if (date != currentDate) {
      currentDate = date;
      group = {value:'', label:date, data:[]};
      acc.push(group);
    }
    // Add item to start of data, update value
    group.data.unshift(item);
    group.value = group.data[group.data.length - 1].y - group.data[0].y;
    
    return acc;
  }, []);
  
  return dayGroups;
}

function processConfigs(dayGroups, config) {
  // Convert {hr, min} to ms
  let configTimeToMs = ({hr, min}) => hr*3.6e6 + min*6e4;
  // Get ms since start of UTC day
  let dateTimeToMs = (date) => date % 8.64e7;

  // For each dayGroup, collect data for each config
  return dayGroups.reduce((acc, dayGroup) => {
    // Create a new configGroup
    let configGroup = {value:dayGroup.value, label:dayGroup.label, data:[]};
    acc.push(configGroup);
    
    // For each config, add data to configGroup.data
    config.forEach(config => {
      let configStart = configTimeToMs(config.startTime);
      let configEnd = configTimeToMs(config.endTime);
      let configObj = {value: '', label: config.label};

      // Add data for each day
      let groupFirstValue = null;
      dayGroup.data.forEach(day => {
        let dayMs = dateTimeToMs(day.x);
        // If falls in config time range
        if (dayMs >=configStart && dayMs <= configEnd) {
          // If groupFirstValue not already set
          if (!groupFirstValue) {
            groupFirstValue = day.y;
          }
          // Update value
          configObj.value = day.y - groupFirstValue;
        }
      });
      // If value is empty, there are no days for this config so don't add
      if (configObj.value !== '') {
        configGroup.data.push(configObj);
      }
    });
    return acc;
  }, []);
}

let dayGroups = groupByDay(data);
// console.log(dayGroups);
console.log(processConfigs(dayGroups, configurations));

于 2021-10-29T05:43:49.680 回答