【问题标题】:How to functionally aggregate individual timestamps into time ranges如何在功能上将单个时间戳聚合到时间范围中
【发布时间】:2017-08-13 01:32:57
【问题描述】:

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

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

我有一个来自数据库的行列表,其中包含“时间”列。

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

我想取这个数据集,并吐出一个不同的数据集,如下所示:

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

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

【问题讨论】:

  • 谁投了反对票 - 我能找到理由吗?

标签: javascript dictionary filter functional-programming reduce


【解决方案1】:

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

【讨论】:

  • 抛开可读性不谈——这正是我一直在寻找的方法!太棒了
  • 遗憾的是,正是出于这个原因,我在日常生活中并没有使用太多的 javascript FP。在严格遵守范式的同时,我似乎无法使其具有可读性。我不喜欢将两者混为一谈,因为那时我宁愿采用传统方法。这些功能真的只适用于更简单的转换 IMO
  • 很有趣 - 我可能不会出于可读性目的使用此解决方案,但它确实回答了我的问题,所以先生为你打勾
  • 谢谢,只是出于好奇-您可以在数据库服务器上进行此聚合吗?
【解决方案2】:

你可以这样做:

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 中的不同时间间隔的行分类,然后从中创建所需的结果数组。

【讨论】:

  • 我不得不更改 currTime 变量,因为它导致了一些奇怪的行为 - 但就目前而言,因为我现在总是使用 1 小时的时间框,关键实际上可能只是小时。我选择了 'var currTime = row["time"].split(':')[0];' 'var key = currTime + ":00";'不过效果很好,谢谢!
  • @aspiring_expert 很高兴我能帮上忙。 :)
  • 我还是忍不住想,还有一种更简单、更聪明的方法可以尝试实现这个目标。也许它不存在 - 但无论如何我都很感激这个答案!
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

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

    这里,getInterval 应该返回指定时间值的时间间隔(例如,您可以使用Math.floor 实现它)。 它会产生一个像这样的对象:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-09
      • 2021-10-27
      • 2017-02-10
      • 2019-08-06
      • 2012-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多