将JSON数据分组为数周/月而无需额外的外部库?

时间:2016-03-23 17:19:15

标签: javascript jquery json

我正在寻找一种解决方案,将数据分组为数周/月而无需外部库。我在这里看到了D3.js nest()选项:how can i group JSON data into the weeks according to calender?

这是使用npm的另一种方式:https://www.npmjs.com/package/group-by-time

也许我在拨号时代已经长大了,但是我仍然希望在页面上加载多少东西,直到实际需要的东西,而不是加载所有可能的东西,以防我想要使用它即使用户“可能”已经拥有来自CDN的缓存副本。

我目前正在使用Chart.js来显示数据,也可以使用Bootstrap和jQuery。我希望能够在一天,一个月之间切换图表,只使用javascript或jQuery,这似乎应该是一个相当普遍的事情,但我没有看到任何例子,如果没有像我提到的更大的库上方。

var chart={
                dates: ['2015-09-01', '2015-09-02', '2015-09-03', '2015-09-04', '2015-09-05', '2015-09-06', '2015-09-07', '2015-09-08', '2015-09-09', '2015-09-10', '2015-09-11', '2015-09-12', '2015-09-13', '2015-09-14', '2015-09-15', '2015-09-16', '2015-09-17', '2015-09-18', '2015-09-19', '2015-09-20', '2015-09-21', '2015-09-22', '2015-09-23', '2015-09-24', '2015-09-25', '2015-09-26', '2015-09-27', '2015-09-28', '2015-09-29', '2015-09-30', '2015-10-01', '2015-10-02', '2015-10-03', '2015-10-04', '2015-10-05', '2015-10-06', '2015-10-07', '2015-10-08', '2015-10-09', '2015-10-10', '2015-10-11', '2015-10-12', '2015-10-13', '2015-10-14', '2015-10-15', '2015-10-16', '2015-10-17', '2015-10-18', '2015-10-19', '2015-10-20', '2015-10-21', '2015-10-22', '2015-10-23', '2015-10-24', '2015-10-25', '2015-10-26', '2015-10-27', '2015-10-28', '2015-10-29', '2015-10-30', '2015-10-31', '2015-11-01', '2015-11-02', '2015-11-03', '2015-11-04', '2015-11-05', '2015-11-06', '2015-11-07', '2015-11-08', '2015-11-09', '2015-11-10', '2015-11-11', '2015-11-12', '2015-11-13', '2015-11-14', '2015-11-15', '2015-11-16', '2015-11-17', '2015-11-18', '2015-11-19', '2015-11-20', '2015-11-21', '2015-11-22', '2015-11-23', '2015-11-24', '2015-11-25', '2015-11-26', '2015-11-27', '2015-11-28', '2015-11-29', '2015-11-30', '2015-12-01', '2015-12-02', '2015-12-03', '2015-12-04', '2015-12-05', '2015-12-06', '2015-12-07', '2015-12-08', '2015-12-09', '2015-12-10', '2015-12-11', '2015-12-12', '2015-12-13', '2015-12-14', '2015-12-15', '2015-12-16', '2015-12-17', '2015-12-18', '2015-12-19', '2015-12-20', '2015-12-21', '2015-12-22', '2015-12-23', '2015-12-24', '2015-12-25', '2015-12-26', '2015-12-27', '2015-12-28', '2015-12-29', '2015-12-30', '2015-12-31', '2016-01-01', '2016-01-02', '2016-01-03', '2016-01-04', '2016-01-05', '2016-01-06', '2016-01-07', '2016-01-08', '2016-01-09', '2016-01-10', '2016-01-11', '2016-01-12', '2016-01-13', '2016-01-14', '2016-01-15', '2016-01-16', '2016-01-17', '2016-01-18', '2016-01-19', '2016-01-20', '2016-01-21', '2016-01-22', '2016-01-23', '2016-01-24', '2016-01-25', '2016-01-26', '2016-01-27', '2016-01-28', '2016-01-29', '2016-01-30', '2016-01-31', '2016-02-01', '2016-02-02', '2016-02-03', '2016-02-04', '2016-02-05', '2016-02-06', '2016-02-07', '2016-02-08', '2016-02-09', '2016-02-10', '2016-02-11', '2016-02-12', '2016-02-13', '2016-02-14', '2016-02-15', '2016-02-16', '2016-02-17', '2016-02-18', '2016-02-19', '2016-02-20', '2016-02-21', '2016-02-22', '2016-02-23', '2016-02-24', '2016-02-25', '2016-02-26', '2016-02-27', '2016-02-28', '2016-02-29'],
                data: [77.02, 63.80, 21.64, 86.60, 65.40, 46.25, 27.38, 66.65, 67.25, 65.59, 64.80, 01.00, 32.75, 04.30, 51.92, 02.75, 40.20, 72.30, 62.90, 83.60, 66.66, 37.30, 93.90, 01.50, 55.77, 50.00, 73.20, 30.03, 07.95, 21.65, 07.93, 66.94, 11.72, 33.75, 22.80, 14.55, 68.78, 66.78, 52.35, 06.24, 64.78, 22.21, 19.08, 23.69, 54.40, 39.55, 28.76, 22.25, 09.85, 07.50, 22.47, 75.94, 93.34, 16.29, 28.98, 64.40, 78.68, 30.65, 96.65, 99.35, 77.50, 75.30, 89.85, 97.50, 53.90, 97.55, 28.98, 75.08, 25.66, 41.00, 73.72, 68.50, 95.40, 49.50, 32.50, 86.00, 05.43, 88.19, 50.39, 03.90, 82.90, 53.78, 94.20, 82.40, 12.63, 78.80, 07.50, 66.50, 41.75, 91.25, 34.50, 22.50, 85.50, 80.00, 33.75, 59.50, 52.50, 73.25, 76.50, 38.75, 11.00, 55.00, 37.25, 92.50, 74.75, 55.75, 37.25, 61.01, 90.95, 87.65, 99.08, 84.49, 47.00, 72.20, 45.95, 44.35, 10.90, 27.05, 63.10, 63.50, 66.48, 97.25, 39.85, 81.50, 57.90, 02.78, 72.95, 41.55, 39.44, 15.85, 06.60, 13.60, 87.10, 86.40, 90.75, 48.30, 29.75, 16.25, 20.51, 45.40, 51.10, 82.00, 24.24, 92.88, 81.75, 18.50, 89.15, 55.75, 53.50, 74.90, 41.35, 61.40, 07.80, 56.80, 33.75, 75.02, 78.50, 46.10, 39.25, 95.00, 22.85, 36.00, 43.53, 63.80, 32.85, 88.30, 89.69, 05.75, 16.15, 15.25, 20.55, 44.50, 46.28, 71.75, 19.45, 41.75, 25.75, 09.05, 58.77, 76.20, 30.45, 71.75]
            };

2 个答案:

答案 0 :(得分:1)

我假设日期格式为YYYY-MM-DD,并且为方便起见,我将日期和数据保存在不同的数组中。

var dates = chart.dates;
var data = chart.data;

牢记上述假设,您可以轻松地按月分组数据。

var groupByMonth = {};
dates.forEach(function (d, i) {

    var v = data[i];  
    var monthYear = d.slice(0, 7);    
    if (groupByMonth.hasOwnProperty(monthYear)) {
        groupByMonth[monthYear].push(v);
    } else {
        groupByMonth[monthYear] = [v];
    }
});

console.log(groupByMonth)

然而,要按周分组,您需要找到周数。这是一个扩展方法:

Date.prototype.getWeekNumber = function(){
    var d = new Date(+this);
    d.setHours(0,0,0);
    d.setDate(d.getDate()+4-(d.getDay()||7));
    return Math.ceil((((d-new Date(d.getFullYear(),0,1))/8.64e7)+1)/7);
};

使用上述扩展方法,您也可以轻松按周编号对数据进行分组。每周重复一周的数字,因此,我使用周和年的组合来明确识别任何一周。

var groupByWeek = {};
dates.forEach(function (d, i) {

    var v = data[i];
    var weekYear = d.slice(0, 4) + '-' + new Date(d).getWeekNumber();
    if (groupByWeek.hasOwnProperty(weekYear)) {
        groupByWeek[weekYear].push(v);
    } else {
        groupByWeek[weekYear] = [v];
    }
});

console.log(groupByWeek)

答案 1 :(得分:1)

@Adnan Umer的解决方案可能对你的情况更好,因为你已经将日期作为字符串,但是如果你有日期而不是字符串,这里有一个更通用的方法:

function roundDate(date,type){
  var d = new Date(date) // so as to not override

  var types = ["day","week","month"]
  var idx = types.indexOf(type)

  if(idx > -1){ // remove all less than day
     d.setMilliseconds(0)
     d.setSeconds(0)
     d.setMinutes(0)
     d.setHours(0)
     if(idx > 0){ //remove day of the week
         d.setDate(d.getDate() - d.getDay()) // make it a sunday
         if(idx > 1){ //remove day of month
             d.setDate(1) 
         }
     }
  }

  return d;

}

function parseDate(str){ // in your case, we need to keep the date disregarding the locale offset
  return new Date(new Date(str).getTime() + new Date().getTimezoneOffset()*60*1000)
}


var lastDate = null
var grouping = "month"

var datesGrouped = []
var dataGrouped = []

function addToLast(arr,val){return arr[arr.length-1]+=val}

//I am assumming your dates are already sorted

chart.dates.map(function(date,index){
    data = chart.data[index] // get corresponding data point
    var group = roundDate(parseDate(date),grouping).getTime()
    if(group == lastDate){
        addToLast(dataGrouped, data)
    }else{
        datesGrouped.push(group)
        dataGrouped.push(data)
        lastDate = group
    }
})

console.log(datesGrouped, dataGrouped)