如何在功能上将单个时间戳聚合到时间范围内
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));
抱歉标题,如果你能想到更好的,请编辑!
我最近开始尝试在 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));