如何在功能上将单个时间戳聚合到时间范围内

How to functionally aggregate individual timestamps into time ranges

抱歉标题,如果你能想到更好的,请编辑!

我最近开始尝试在 JavaScript 中使用更多 map/filter/reduce 操作,我有一个问题正在尝试解决,我想知道这样做的最佳功能方法!

我有一个来自数据库的行列表,其中有一个 'time' 列。

{[x, y, 15:10, z], [x, y, 15:20, z], [x, y, 16:10, z]}

我想使用这个 data-set,并吐出一个不同的数据集,如下所示:

[{timebox: "15:00-16:00", count: 2}, {timebox: "16:00-17:00", count: 1}]

我可以想办法做到这一点,其中包括几个操作(例如只为每个 'time-box' 编写几个过滤语句)但是我想问有没有一种干净、简单的方法来实现这个?

您可以使用类似于 Underscore 的 countBy (docs)

_.countBy(
    (row) => { return getInterval(row[2]); }
);

这里,getInterval应该return指定时间值的时间间隔(你可以用Math.floor来实现)。 它会产生一个像这样的对象:

{
    "15:00-16:00": 2,
    "16:00-17:00": 1
}

从这里开始,转成数组应该很简单了。

您可以拆分时间,只为哈希对象取小时部分。

function getTimebox(t) {
    return [t, (+t + 1) % 24].map(v => ('00' + v).slice(-2) + ':00').join('-');
}

var array = [['x', 'y', '15:10', 'z'], ['x', 'y', '15:20', 'z'], ['x', 'y', '16:10', 'z'], ['x', 'y', '23:23', 'z']],
    result = array.reduce(function (hash) {
        return function (r, a) {
            var timebox = a[2].split(':')[0];
            if (!hash[timebox]) {
                hash[timebox] = { timebox: getTimebox(timebox), count: 0 };
                r.push(hash[timebox]);
            }
            hash[timebox].count++;
            return r;
        };
    }(Object.create(null)), []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

使用 Map

更紧凑的样式

var getT = t => [t, (+t + 1) % 24].map(v => ('00' + v).slice(-2) + ':00').join('-'),
    array = [['x', 'y', '15:10', 'z'], ['x', 'y', '15:20', 'z'], ['x', 'y', '16:10', 'z'], ['x', 'y', '23:23', 'z']],
    result = array.reduce(
        (map => (r, a) => 
            (t =>
                (!map.has(t) && map.set(t, r[r.push({ timebox: getT(t), count: 0 }) - 1]), map.get(t).count++, r)
            )(a[2].split(':')[0])
        )(new Map), []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

你可以这样做:

var rows = [
  ['x', 'y', '15:10', 'z'], 
  ['x', 'y', '15:20', 'z'], 
  ['x', 'y', '16:10', 'z']
];

var sets = rows.reduce(function(set, row) {
  var currTime = +row[2].split(':')[0] + (+row[2].split(':')[1])/24;
  var key = Math.floor(currTime) + '-' + Math.ceil(currTime);
  set[key] = set[key] || [];
  set[key].push(row);
  return set;
}, {});

var result = Object.keys(sets).map(function(key) {
  return {
    'timebox' : key,
    'count' : sets[key].length
  }
});

console.log(result);

基本上,这会将存储在 sets 中的不同时间间隔的行分类,然后从中创建所需的结果数组。

使用reduce 和filter 的实现。不使用散列或映射类型对象,因此对聚合数组的查找是在线性时间内完成的。

var x = [["x", "y", "15:10", "z"], ["x", "y", "15:20", "z"], ["x", "y", "16:10", "z"]];

var y = x.reduce(function(e,i) {
          if (e.filter((n) => n.timebox == i[2].split(':')[0]+ ":00"+ "-" + (parseInt(i[2].split(':')[0])+1)+ ":00").length == 0)
           e.push({timebox: i[2].split(':')[0] + ":00" + "-" + (parseInt(i[2].split(':')[0])+1)+ ":00", count: 0});
            
          e.filter((n) => n.timebox == i[2].split(':')[0]+ ":00"+ "-" + (parseInt(i[2].split(':')[0])+1)+ ":00")[0].count += 1;
          return e;
          }
       ,
      []);
      
      
      alert(JSON.stringify(y));