#javascript #arrays #algorithm
#javascript #массивы #алгоритм
Вопрос:
Я хочу отфильтровать массив, объект, который содержит предпоследнюю дату за тот же период. Например, для "period": 2
. "timestamp": "3/11/2016 02:15:11"
будет ли предпоследняя дата.
Входной массив:
[
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 02:13:11", "amount": 7.25, "period": 2 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 02:15:11", "amount": 7.25, "period": 2 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 06:50:57", "amount": 11.75, "period": 6 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 06:52:45", "amount": 11.75, "period": 6 }
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 06:59:59", "amount": 11.75, "period": 6 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 07:02:54", "amount": 4.5, "period": 7 }
]
Ожидаемый выходной массив:
[
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 02:13:11", "amount": 7.25, "period": 2 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 06:52:45", "amount": 11.75, "period": 6 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 07:02:54", "amount": 4.5, "period": 7 }
]
Ответ №1:
Вот решение, которое sort()
сортирует все элементы по дате, затем reduce()
сортирует их по периоду и map()
в результате Object.values()
возвращает второй элемент или первый, если есть только один.
const input = [
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 02:15:11", "amount": 7.25, "period": 2 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 02:13:11", "amount": 7.25, "period": 2 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 06:50:57", "amount": 11.75, "period": 6 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 06:52:45", "amount": 11.75, "period": 6 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 06:59:59", "amount": 11.75, "period": 6 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 07:02:54", "amount": 4.5, "period": 7 }
]
// sort by timestamp
input.sort(function(a,b){
return new Date(b.timestamp) - new Date(a.timestamp);
});
const filtered = Object.values(input
// reduce by period
.reduce((acc, o) =>
(acc[o.period] = [...acc[o.period] ?? [], { ...o }], acc), {}))
// map and return the second element if it exists, otherwise the first.
.map((v) => v[1] ?? v[0]);
console.log(filtered);
Ответ №2:
Это работает для вас?
let arr =[
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 02:13:11", "amount": 7.25, "period": 2 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 02:15:11", "amount": 7.25, "period": 2 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 06:50:57", "amount": 11.75, "period": 6 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 06:52:45", "amount": 11.75, "period": 6 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 06:59:59", "amount": 11.75, "period": 6 },
{ "ip": "11.11.11.11", "timestamp": "3/11/2016 07:02:54", "amount": 4.5, "period": 7 }
]
let orederedByPeriod = {};
arr.forEach(v => {
if(orederedByPeriod[v.period]){
orederedByPeriod[v.period].push({...v});
} else{
orederedByPeriod[v.period] = [{...v}];
}
});
let response = [];
for(let key in orederedByPeriod){
if(orederedByPeriod[key].length === 1){
response.push(orederedByPeriod[key][0]);
} else{
orederedByPeriod[key].sort((a, b) => new Date(a.timestamp) > new Date(b.timestamp) ? 1 : -1);
response.push(orederedByPeriod[key][orederedByPeriod[key].length -2]);
}
}
console.log(response);