问题很简单:我有一系列项目,每个项目都有一个日期。根据日期,我想将此数组拆分为几个数组。
就我而言,我想将数组分为3个数组:一个包含最后24小时的结果,另一个包含48小时的结果,然后包含一周中的最后一个结果。
这里是对案件的最小复制,带有最终解决方案。
const now = Date.now();
const day = 1000 * 3600 * 24;
const todayTime = now - day;
const yesterdayTime = now - day * 2;
const weekTime = now - day * 7;
const arr = [
{ id: 1, date: todayTime + 100 },
{ id: 2, date: yesterdayTime + 100 },
{ id: 3, date: weekTime + 100 },
];
const today = arr.filter(item => item.date - todayTime > 0);
const yesterday = arr.filter(item => item.date - yesterdayTime > 0 && item.date - todayTime < 0);
const week = arr.filter(item => item.date - weekTime > 0 && item.date - yesterdayTime < 0);
console.log(today, yesterday, week);
有没有一种方法可以使其更简洁?我在说代码长度:我想将其减少到最大,尤其是3个数组的定义。我尝试使用reduce,但是语法非常丑陋。
有什么想法吗?
答案 0 :(得分:0)
它并不短,但是我会选择一个更通用的函数,该函数根据给定的属性(在您的情况下为“ date”)和一些边界值(您有3个)(按升序排列)将数据分组。然后该函数将再返回一个值,因为3个边界将一个无限范围分为4个范围,等等。
这就是该函数的样子:
function groupInRanges(data, prop, boundaries) {
// NB: boundaries must be sorted ascending.
return data.reduce((acc, item) => {
let index = boundaries.findIndex(boundary => item[prop] < boundary);
if (index < 0) index = boundaries.length;
acc[index].push(item);
return acc;
}, [[], ...boundaries.map(() => [])]);
}
// Demo
const now = Date.now();
const day = 1000 * 3600 * 24;
const arr = [
{ id: 1, date: now - day + 100 },
{ id: 2, date: now - 2*day + 100 },
{ id: 3, date: now - 5*day },
];
// We are not interested in the first value (data older than 1 week):
const [, week, yesterday, today] = groupInRanges(arr, "date", [now-day*7, now-day*2, now-day]);
console.log(today, yesterday, week);
请注意,如果您的数据可能具有未来日期,则需要将一个额外的边界设置为now
。
这假定不存在任何早于一周或未来的数据。使用三元运算符确定应在哪个数组中推送数据项:
const now = Date.now();
const day = 1000 * 3600 * 24;
const todayTime = now - day;
const yesterdayTime = now - day * 2;
const weekTime = now - day * 7;
const arr = [
{ id: 1, date: todayTime + 100 },
{ id: 2, date: yesterdayTime + 100 },
{ id: 3, date: weekTime + 100 },
];
const [today, yesterday, week] = arr.reduce((acc, item) => {
acc[item.date > todayTime ? 0 : item.date > yesterdayTime ? 1 : 2].push(item);
return acc;
}, [[], [], []]);
console.log(today, yesterday, week);
使用逗号运算符和表达式箭头功能语法,虽然有点短,但可读性较差:
const [today, yesterday, week] = arr.reduce((acc, item) =>
(acc[item.date > todayTime ? 0 : item.date > yesterdayTime ? 1 : 2].push(item), acc)
, [[], [], []]);
答案 1 :(得分:0)
您可以将函数移到数组中并获取索引,以供以后推送该项目。
out = []
while len(l)>0:
first, *rest = l
first = set(first)
lf = -1
while len(first)>lf:
lf = len(first)
print(lf)
rest2 = []
for r in rest:
if len(first.intersection(set(r)))>0:
first |= set(r)
else:
rest2.append(r)
rest = rest2
out.append(first)
l = rest
答案 2 :(得分:0)
您想使下面的部分更简洁吗?
const today = arr.filter(item => item.date - todayTime > 0);
const yesterday = arr.filter(item => item.date - yesterdayTime > 0 && item.date - todayTime < 0);
const week = arr.filter(item => item.date - weekTime > 0 && item.date - yesterdayTime < 0);
这是我尝试过的:
const [today, yesterday, week] = arr.reduce((result, item) => (index = item.date - todayTime > 0 ? 0 : item.date - yesterdayTime > 0 && item.date - todayTime < 0 ? 1 : 2, result[index].push(item), result), [[], [], []])
最终代码是:
const now = Date.now();
const day = 1000 * 3600 * 24;
const todayTime = now - day;
const yesterdayTime = now - day * 2;
const weekTime = now - day * 7;
const arr = [
{ id: 1, date: todayTime + 100 },
{ id: 2, date: yesterdayTime + 100 },
{ id: 3, date: weekTime + 100 },
];
// revised
const [today, yesterday, week] = arr.reduce((result, item) => (index = item.date - todayTime > 0 ? 0 : item.date - yesterdayTime > 0 && item.date - todayTime < 0 ? 1 : 2, result[index].push(item), result), [[], [], []])
console.log(today, yesterday, week)
答案 3 :(得分:0)
与其他大多数答案一样,这是使用map
而不是reduce
的另一种选择。
这只是通过比较日期,如果它符合特定条件,就从数组中删除item
来工作。在下面的示例中,我复制了数组,保留了旧的arr
不变。但是,如果您不关心arr
的变异,或者想要查看哪些项目不符合任何条件(因为它们被遗忘了),则可以简单地忽略它。
我需要reverseEach
函数的原因很明显。如果我开始从当前正在迭代元素的数组中删除项目,则开始转移。从后到前迭代时,这没关系,因为我已经处理了这些项目。
在下面的示例中,订单很重要。当您将t1w
(时间1周)放置为数组中的第一个元素时,arr
的所有元素都将符合条件,并将出现在该组中。确保您提供的标准是递增的(或递减的,取决于上下文)。
// define some helpers
Array.prototype.deleteAt = function (index) { return this.splice(index, 1)[0]; };
Array.prototype.dup = function () { return this.slice(0); };
Array.prototype.reverseEach = function (callback, thisArg) {
if (thisArg !== undefined) callback = callback.bind(thisArg);
for (let index = this.length - 1; index >= 0; index -= 1) {
callback(this[index], index, this);
}
};
// initialisation
const now = Date.now();
const day = 1000 * 3600 * 24;
const t1d = now - day;
const t2d = now - day * 2;
const t1w = now - day * 7;
const arr = [
{ id: 1, date: t1d + 100 },
{ id: 2, date: t2d + 100 },
{ id: 3, date: t1w + 100 },
];
// actual answer
const groups = [t1d, t2d, t1w].map(function (limit) {
const group = [];
this.reverseEach((item, index) => {
if (item.date > limit) group.unshift(this.deleteAt(index));
});
return group;
}, arr.dup());
console.log(groups);