【问题标题】:In javascript, how do I create a nested array or object from json data?在 javascript 中,如何从 json 数据创建嵌套数组或对象?
【发布时间】:2017-05-27 09:06:44
【问题描述】:

这是对之前提出的问题 (In javascript, how do I extract the month from date string "yyyy-mm-dd" or timeStamp?) 的修改,@mhodges 很好地解决了这个问题。

由于修改的性质,我认为只创建一个新问题是合适的。

我有一个数据库,其中某些记录的事件作为 json 对象,每个都有它自己的 JS 毫秒时间戳,还有一个格式为“yyyy-mm-dd”的日期字符串,以及一个分钟条目。

我想将时间戳用作算法的输入,该算法将计算在给定月份和年份输入的日志数量。

我还希望算法能够将给定月份和年份的累计记录分钟数相加。

例如,

log1: {
    Date:"2017-05-24",
    TimeStamp:1495612800,
    Minutes: 15},
log2: {
    Date:"2017-05-19",
    TimeStamp:1495180800,
    Minutes: 45},
log3: {
    Date:"2017-04-24",
    TimeStamp:1493020800,
    Minutes:30},
log4: {
    Date:"2016-08-15",
    TimeStamp:1471248000,
    Minutes:75}

在本例中,算法将统计 2017 年 5 月有两份日志,一份在 2017 年 4 月,一份在 2016 年 8 月。

该算法还将返回 2017 年 5 月的 60 分钟、2017 年 4 月的 30 分钟和 2016 年 8 月的 75 分钟的总和。

对于将 @mhodges 之前提供的解决方案(参见 (In javascript, how do I extract the month from date string "yyyy-mm-dd" or timeStamp?))修改为适当的嵌套输出的任何帮助,我们将不胜感激!

我无法修改@mhodges 解决方案来实现它,但设想如下:

{
  "2016":{
    "8": {
      occurrences: 1,
      minutes: 75
    }
  },
  "2017":{
    "4": {
      occurrences: 1,
      minutes: 30
    },
    "5": {
      occurrences: 2,
      minutes: 60
    }
  }
}

谢谢

【问题讨论】:

    标签: javascript algorithm date


    【解决方案1】:

    从您的预期输出来看,您可能希望使用日期值而不是时间戳。您可以循环浏览日志并将每个月的分钟数相加。

    看起来像这样:

    var logs = [{
        Date: "2017-05-24",
        TimeStamp: 1495612800,
        Minutes: 15
      },
      {
        Date: "2017-05-19",
        TimeStamp: 1495180800,
        Minutes: 45
      },
      {
        Date: "2017-04-24",
        TimeStamp: 1493020800,
        Minutes: 30
      },
      {
        Date:"2016-08-15",
        TimeStamp:1471248000,
        Minutes:75
      }
    ];
    
    var result = {};
    for (var i = 0; i < logs.length; i++) {
      var year = logs[i].Date.slice(0, 4);
      var month = logs[i].Date.slice(5, 7);
      if (!result[year]) {
        result[year] = {};
      }
      if (!result[year][month]) {
        result[year][month] = {
          occurences: 1,
          minutes: logs[i].Minutes
        }
        continue;
      }
      result[year][month].occurences++;
      result[year][month].minutes += logs[i].Minutes;
    }
    
    console.log(result);

    【讨论】:

    • 非常感谢您的解决方案。我之所以选择它,是因为它似乎是我使用给定设置实现的最简单的解决方案,可以实现我想要实现的目标。虽然,我继续使用timeStamp,只是稍微修改了一下。
    【解决方案2】:

    使用Array.prototype.mapArray.prototype.reduce 以及一些内置的 Date 方法似乎是一个很好的问题。

    const logs = [
      {
        Date:"2017-05-24",
        TimeStamp:1495612800,
        Minutes: 15
      },
      {
        Date:"2017-05-19",
        TimeStamp:1495180800,
        Minutes: 45
      },
      {
        Date:"2017-04-24",
        TimeStamp:1493020800,
        Minutes:30
      },
      {
        Date:"2016-08-15",
        TimeStamp:1471248000,
        Minutes:75
      }]
    
    // mapping over the logs, transforming each so that we have data in the right form (ie. years, months, and minutes; occurences we'll get later).
    const flat = logs.map(log => {
      const date = new Date(log.Date)
      return {
        year: date.getFullYear(),
        month: date.getMonth() + 1,
        minutes: log.Minutes, 
      }
    })
    
    const hierarchy = flat.reduce((hier, log) => {
      // As we're building the result, we need to init things if they don't already exist
      hier[log.year] = hier[log.year] || {}
      // The lowest level will have this form
      hier[log.year][log.month] = hier[log.year][log.month] || 
        {
          occurences: 0,
          minutes: 0
        }
      
      // Accumulate minutes and occurences as we go
      hier[log.year][log.month].minutes += log.minutes
      hier[log.year][log.month].occurences += 1
    
      return hier
    }, {})
    
    console.log(hierarchy)

    【讨论】:

    • 感谢您的解决方案。我认为它肯定会奏效。我不确定堆栈溢出是如何真正起作用的,但如果有帮助,我很高兴为您竖起大拇指或打勾。
    【解决方案3】:

    这里有一个破解。

    let i = arr.length;
    let obj = {};
    while(i--){
      let [year, month, day] = arr[i].Date.split('-');
    
      //probably a better way of initializing a hashtree.
      if(!obj[year]){ obj[year] = {}; } 
      if(!obj[year][month]){ obj[year][month] = {}}
    
      let occur = obj[year][month]['occurences'] 
      let minutes = obj[year][month]['minutes'] 
    
      obj[year][month]['occurences'] = (occur === undefined) ? 1 : occur + 1;
      obj[year][month]['minutes'] = (minutes === undefined) ? arr[i].Minutes : arr[i].Minutes + minutes;
    }
    

    https://jsfiddle.net/25n4jo4e/

    【讨论】:

    • 感谢您的解决方案。它绝对是优雅的,我仍然可以修改我的代码来使用它,因为我不需要做太多的改变。我不确定堆栈溢出是如何真正起作用的,但如果有帮助,我很高兴为您竖起大拇指或打勾。
    猜你喜欢
    • 2019-06-22
    • 2019-04-23
    • 1970-01-01
    • 1970-01-01
    • 2016-09-04
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    相关资源
    最近更新 更多