Recently I've been testing some things and I've stuck on little piece of code. Here's a sketch:
let data = [{
date: "2018-10-09 18:00",
temp: "+13"
},
{
date: "2018-10-09 21:00",
temp: "+12"
},
{
date: "2018-10-10 00:00",
temp: "+5"
},
{
date: "2018-10-10 15:00",
temp: "+18"
},
{
date: "2018-10-11 00:00",
temp: "+4"
},
{
date: "2018-10-11 00:00",
temp: "+4"
}
];
let res = [];
function setData(data, day, time, id) {
let a = {
day: day,
time: time,
temp: data.temp
}
res[id].push(a);
}
function parse(data) {
let day, time, id = -1;
for (let i = 0; i < data.length; i++) {
day = data[i].date.split(" ")[0];
time = data[i].date.split(" ")[1];
if (id !== 0 && id !== -1) {
setData(data[i], day, time, id);
} else {
id++;
res[id] = new Array();
setData(data[i], day, time, id);
}
}
}
parse(data);
console.log(res);
I need to parse data and sort different days in way like this:
res = [[{day: 2018-10-09}, {day: 2018-10-09}], [{day: 2018-10-10}, {day: 2018-10-10}], [{day: 2018-10-11}, {day: 2018-10-11}]]
But my code isn't right, and I've done so many attempts and I've failed. Please help me
You need to revise your approach, there's no logic that would group the dates in it. Try the following code instead:
let data = [
{
date: "2018-10-09 18:00",
temp: "+13"
},
{
date: "2018-10-10 00:00",
temp: "+5"
},
{
date: "2018-10-09 21:00",
temp: "+12"
},
{
date: "2018-10-10 15:00",
temp: "+18"
},
{
date: "2018-10-11 00:00",
temp: "+4"
},
{
date: "2018-10-11 00:00",
temp: "+4"
}
];
let res = {};
function setData(data, day, time){
let a = {
day: day,
time: time,
temp: data.temp
}
res[day].push(a);
}
function parse(data) {
let day, time, output = [];
for (let i = 0; i < data.length; i++) {
day = data[i].date.split(" ")[0];
time = data[i].date.split(" ")[1];
res[day] = res[day] || [];
setData(data[i], day, time);
}
let sortedDates = Object.keys(res).sort();
for (let date of sortedDates) {
output.push(res[date]);
}
return output;
}
res = parse(data);
console.log(res);
If you also want to sort the inner arrays then you can take a look at sort with compare function
Try this, hope it helps! Cheers
let data = [
{
date: "2018-10-09 18:00",
temp: "+13"
},
{
date: "2018-10-09 21:00",
temp: "+12"
},
{
date: "2018-10-10 00:00",
temp: "+5"
},
{
date: "2018-10-10 15:00",
temp: "+18"
},
{
date: "2018-10-11 00:00",
temp: "+4"
},
{
date: "2018-10-11 00:00",
temp: "+4"
}
];
let res = [];
function setData(data, day, time, id){
let a = {
day: day,
time: time,
temp: data.temp
}
res[id].push(a);
}
function parse(data) {
let day, time, lastDay, id = 0;
for (let i = 0; i < data.length; i++) {
day = data[i].date.split(" ")[0];
time = data[i].date.split(" ")[1];
if (i == 0) {
res.push([]);
setData(data[i], day, time, id);
} else {
lastDay = data[i-1].date.split(" ")[0];
if(day.localeCompare(lastDay) == 0) {
// Same day
setData(data[i], day, time, id);
} else {
// Another day
id++;
res.push([]);
setData(data[i], day, time, id);
}
}
}
}
parse(data);
console.log(res);
A slightly different approach by using a Map.
var data = [{ date: "2018-10-09 18:00", temp: "+13" }, { date: "2018-10-09 21:00", temp: "+12" }, { date: "2018-10-10 00:00", temp: "+5" }, { date: "2018-10-10 15:00", temp: "+18" }, { date: "2018-10-11 00:00", temp: "+4" }, { date: "2018-10-11 00:00", temp: "+4" }],
result = Array.from(
data
.reduce(
(m, { date, temp }) => (
([day, time]) => m.set(day, (m.get(day) || []).concat({ day, time, temp })))
(date.split(' ')),
new Map
)
.values(),
a => a.sort((a, b) => a.time.localeCompare(b.time))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Related
I need to calculate which is the next closer hour to "time" taking into account the following array data:
var date = new Date();
var time = date.getHours(); // 17 -> it means 5:00 PM
var minute = date.getMinutes(); // 12
// This is how the data has been saved in the database.
{ id: ‘1’, time: '1:00 AM' }
{ id: ‘1’, time: '2:00 PM' }
{ id: ‘1’, time: '7:00 PM' }
{ id: ‘1’, time: '10:00 PM' }
{ id: ‘1’, time: '8:00 PM' }
{ id: ‘1’, time: '11:00 AM' }
{ id: ‘2’, time: '9:00 AM' }
{ id: ‘2’, time: '6:30 PM' }
{ id: ‘2’, time: '5:00 PM' }
{ id: ‘2’, time: '1:00 PM' }
The result need to be an array like this:
{id: ‘1’, time: '7:00 PM'}
{id: ‘2’, time: '6:30 PM'}
Basically I need to know which is the next closer time to 5:12 PM for each ID.
This is my code so far:
function calculateNextPill(items) {
let nextPillArr = [];
let itemData = null;
let item_id = null;
var currentTime = new Date();
var closerTime = new Date();
var newTimes = [];
for(i=0; i<items.length; i++) {
itemData = items[i].itemdata[0];
item_id = items[i]._id;
for (const prop in itemData.pills) {
const pill = itemData.pills[prop];
if (pill != undefined && pill.time != undefined) {
nextPillArr.push({id: item_id, time: pill.time});
}
}
}
nextPillArr.forEach(element => {
var time = element.time;
var scheduleTime = new Date();
var parts = time.match(/(\d+):(\d+) (AM|PM)/);
if (parts) {
var hours = parseInt(parts[1]),
minutes = parseInt(parts[2]),
tt = parts[3];
if (tt === 'PM' && hours < 12) hours += 12;
scheduleTime.setHours(hours, minutes, 0, 0);
var a = moment(currentTime);
var b = moment(scheduleTime);
b.diff(a);
newTimes.push({id: element._id, diff: b.diff(a)});
// here I need to calculate which time is closer for which pill. Not done yet. Need more coffe...
}
});
}
First you need a function that lets you get some kind of numeric value for each time that you can then use to compare the values. The following function will give us the amount of minutes in 24h format:
function time_to_numeric(time) {
const [_, h, m, meridian] = time.match(/(\d+):(\d+) (AM|PM)/);
let [hours, min] = [parseInt(h), parseInt(m)];
if (meridian === "PM" && hours !== 12) hours += 12;
if (meridian === "AM" && hours === 12) hours -= 12;
return hours * 60 + min;
}
Next, we also need the time in the same format for now:
const now = new Date();
const now_numeric = now.getHours() * 60 + now.getMinutes();
Using this, we can now start finding the closest times for each unique id assuming items is an array of all the objects in your example. This works by computing the difference in minutes to now and swapping the value if it lower. In the case of a time occuring earlier than now, we instead compute the difference to that time the next day. We save both the difference and the actual time for the current minimum for each id:
const closer_times_by_id = items.reduce((acc, {id, time}) => {
const time_numeric = time_to_numeric(time);
let diff = time_numeric - now_numeric;
if (diff < 0) diff = time_numeric + MINUTES_PER_DAY - now_numeric;
const prev_diff = acc[id] && acc[id].diff;
if (prev_diff === undefined || diff < prev_diff) {
acc[id] = { diff, time };
}
return acc;
}, {});
Now our closer_times_by_id will look something like {'1': {diff: 158, time: '7:00 PM'}, '2': {diff: 38, time: '5:00 PM'}}. We map this to an array in the following way:
times_arr = Object.entries(closer_times_by_id).map(item => {
const [id, { time }] = item;
return { id, time };
});
After this, we are done and times_arr contains your result.
Full code:
const MINUTES_PER_DAY = 24 * 60;
// Takes a string like '1:10 PM' and returns the amount of minutes in 24h format
function time_to_numeric(time) {
const [_, h, m, meridian] = time.match(/(\d+):(\d+) (AM|PM)/);
let [hours, min] = [parseInt(h), parseInt(m)];
if (meridian === "PM" && hours !== 12) hours += 12;
if (meridian === "AM" && hours === 12) hours -= 12;
return hours * 60 + min;
}
function closest_items_by_id(items) {
const now = new Date();
const now_numeric = now.getHours() * 60 + now.getMinutes();
// Find closest times for each id, giving preference to times in the
// future in case of ties
// After reducing has finished, closer_times_by_id will be an object like
// {'1': {diff: 158, time: '7:00 PM'}, '2': {diff: 38, time: '5:00 PM'}}
const closer_times_by_id = items.reduce((acc, {id, time}) => {
const time_numeric = time_to_numeric(time);
let diff = time_numeric - now_numeric;
// If time occured earlier than now, calculate diff to time next day
if (diff < 0) diff = time_numeric + MINUTES_PER_DAY - now_numeric;
const prev_diff = acc[id] && acc[id].diff;
if (prev_diff === undefined || diff < prev_diff) {
acc[id] = { diff, time };
}
return acc;
}, {});
// Map closer_times_by_id to desired format
return Object.entries(closer_times_by_id).map(item => {
const [id, { time }] = item;
return { id, time };
});
}
const raw_data = [
{ id: '1', time: '1:00 AM' },
{ id: '1', time: '11:00 AM' },
{ id: '1', time: '2:00 PM' },
{ id: '1', time: '7:00 PM' },
{ id: '1', time: '8:00 PM' },
{ id: '1', time: '10:00 PM' },
{ id: '2', time: '9:00 AM' },
{ id: '2', time: '1:00 PM' },
{ id: '2', time: '1:10 PM' },
{ id: '2', time: '5:00 PM' },
{ id: '2', time: '6:30 PM' },
]
const now = new Date();
console.log(`Time at SO-server: ${now.getHours()}:${now.getMinutes()}`);
console.log(closest_items_by_id(raw_data));
I want to make an array of objects grouped by the date property.
let data = [
{ Age: "(60-100)", Date: "28/05/20" },
{ Age: "(60-100)", Date: "28/05/20" },
{ Age: "(4-6)", Date: "28/05/20" },
{ Age: "(60-100)", Date: "29/05/20" },
{ Age: "(38-43)", Date: "29/05/20" },
{ Age: "(4-6)", Date: "29/05/20" },
{ Age: "(38-43)", Date: "30/05/20" },
{ Age: "(38-43)", Date: "30/05/20" }
];
I want the output like
result = [
{ Date: "28/05/20", "(60-100)": 2, "(4-6)": 1 },
{ Date: "29/05/20", "(38-43)": 1, "(4-6)": 1, "(60-100)": 1 },
{ Date: "30/05/20", "(38-43)": 2 },
]
Try this:
function groupByDate(data){
let groupedData = [];
data.forEach(element => {
//Search for the object containing the specified date
let objIndex = groupedData.findIndex(object => {return object.Date == element.Date;})
//If date is not created, create it
if (objIndex == -1){
groupedData.unshift({Date: element.Date})
objIndex = 0;
}
//If age is not created, create it. Else add 1 to specified age.
if(typeof groupedData[objIndex][element.Age] == 'undefined'){
groupedData[objIndex][element.Age] = 1;
} else {
groupedData[objIndex][element.Age]++;
}
});
return groupedData;
}
If you also want to sort by date, you could check out this post.
Hope it helped you!
Give this a try.
let data = [
{ Age: "(60-100)", Date: "28/05/20" },
{ Age: "(60-100)", Date: "28/05/20" },
{ Age: "(4-6)", Date: "28/05/20" },
{ Age: "(60-100)", Date: "29/05/20" },
{ Age: "(38-43)", Date: "29/05/20" },
{ Age: "(4-6)", Date: "29/05/20" },
{ Age: "(38-43)", Date: "30/05/20" },
{ Age: "(38-43)", Date: "30/05/20" }
];
let res = [];
data.map((d, index) => {
if (!res.some(val => val.Date === d.Date)) {
d[`${d.Age}`] = 1
res.push(d)
delete(d.Age)
} else {
let index = res.findIndex(val => val.Date == d.Date);
let _d = res[index];
if (_d.hasOwnProperty(`${d.Age}`)) {
_d[`${d.Age}`] = parseInt(_d[`${d.Age}`] + 1)
} else {
_d[`${d.Age}`] = 1
}
res[index] = _d;
}
})
console.log(res)
try this:
var result={};
for(var item of data) {
if(result[item.Date]==undefined) result[item.Date]={};
if(result[item.Date][item.Age]==undefined) result[item.Date][item.Age]=0;
result[item.Date][item.Age]++;
}
This gives you an object (not an array) with keys of Date and values as object with keys of Age and values as count.
If you still need an array, you can iterate over the result and construct an array.
result=={
"28/05/20": {
"(60-100)": 2,
"(4-6)": 1
},
"29/05/20": {
"(60-100)": 1,
"(38-43)": 1,
"(4-6)": 1
},
"30/05/20": {
"(38-43)": 2
}
}
If you want the array, you can create resultArr=[], iterate over keys of result, tempObj, add key "Date" and value of iterated key, then iterate over keys of iterated key, add each "Age" with it's count, then push tempObj into resultArr...
Condensed version based on #Dante Culaciati approach with optional sort parameter.
const condenseAge = (arr, isSort = true) => {
let r = [];
arr.map((val) => {
let i = r.findIndex(obj => obj.Date == val.Date);
(i < 0) && r.unshift({Date: val.Date}) && (i = 0);
(!r[i][val.Age]) ? r[i][val.Age] = 1 : r[i][val.Age]++;
});
return !isSort?r:r.sort((a,b)=>(ac=a['Date'].split('/'), bc=b['Date'].split('/'), new Date(ac[2],ac[1],ac[0]) - new Date(bc[2],bc[1],bc[0])));
}
console.log(condenseAge([
{ Age: "(4-6)", Date: "02/06/20"},
{ Age: "(60-100)", Date: "28/05/20" },
{ Age: "(60-100)", Date: "28/05/20" },
{ Age: "(4-6)", Date: "28/05/20" },
{ Age: "(60-100)", Date: "29/05/20" },
{ Age: "(38-43)", Date: "29/05/20" },
{ Age: "(4-6)", Date: "29/05/20" },
{ Age: "(38-43)", Date: "30/05/20" },
{ Age: "(38-43)", Date: "30/05/20" }
]));
I have an array of objects having a DateTime, like this:
[{Date1, Count1}, {Date2, Count2}, ...]
The Dates in the array are given by Hour (Date2 = Date1 + 1H), so I am interested in taking only the Date's last hour count.
{Date: 2020-03-21T20:00:00Z, Count: 3}
{Date: 2020-03-21T22:00:00Z, Count: 4}
{Date: 2020-03-21T23:00:00Z, Count: 15}
{Date: 2020-03-22T00:00:00Z, Count: 66}
{Date: 2020-03-22T01:00:00Z, Count: 70}
How can I reduce this Array to take in consideration only the last item of each day?
{Date: 2020-03-21T23:00:00Z, Count: 15}
{Date: 2020-03-22T01:00:00Z, Count: 70}
Something like myArray.groupBy(Date).TakeLast()...
Here's some code that only works if the dates are sorted (if they're not you can just sort via dates.sort((a, b) => a.Date.getTime() - b.Date.getTime()):
var dates = [
{ Date: new Date("2020-03-21T20:00:00Z"), Count: 3 },
{ Date: new Date("2020-03-21T22:00:00Z"), Count: 4 },
{ Date: new Date("2020-03-21T23:00:00Z"), Count: 15 },
{ Date: new Date("2020-03-22T00:00:00Z"), Count: 66 },
{ Date: new Date("2020-03-22T01:00:00Z"), Count: 70 }
];
var lastPerDay = [];
// just need to set to a value that's impossible to get normally
var prevDate = null;
// go backwards through the array to find the last instance
for (var i = dates.length - 1; i >= 0; i--) {
// need some way of combining year, month, and date into a value
var curDate = [dates[i].Date.getUTCFullYear(), dates[i].Date.getUTCMonth(), dates[i].Date.getUTCDate()].join(",");
// we haven't seen the date before
if (curDate !== prevDate) {
// add the day to the front
lastPerDay.unshift(dates[i]);
// update the previous date
prevDate = curDate;
}
}
console.log(lastPerDay);
With this, there is no need for the dates to be sorted.
let lastsHour = {}, array = [
{ date: new Date("2020-03-21T20:00:00Z"), count: 3 },
{ date: new Date("2020-03-21T22:00:00Z"), count: 4 },
{ date: new Date("2020-03-21T23:00:00Z"), count: 15 },
{ date: new Date("2020-03-22T00:00:00Z"), count: 66 },
{ date: new Date("2020-03-22T01:00:00Z"), count: 70 }
];
array.map(function (e) {
let currentDate = ""+e.date.getUTCDate()+e.date.getUTCMonth()+e.date.getUTCFullYear();
if (! lastsHour[currentDate]) {
lastsHour[currentDate] = e;
} else if (lastsHour[currentDate].date < e.date) {
lastsHour[currentDate] = e;
}
});
let result = [];
for (let key in lastsHour ) {
if (lastsHour.hasOwnProperty(key)) {
result.push(lastsHour[key]);
}
}
console.log(result);
We can use reduce method and decide on each iteration whether it is a next hour of current day. Then we can delete an array element which contains previous hour. We have O(N) by using reduce method:
const oneHourInMilliseconds = 3600000;
const result = arr.reduce((a, {Date: date, Count}) => {
let [y, m, d] = date.split(/\D+/);
let key = new Date(date).getTime();
a[key] = a[key] || { Date: date, Count };
if (a[key - oneHourInMilliseconds]) {
let [yPrev, mPrev, dPrev] = a[key - oneHourInMilliseconds].Date.split(/\D+/);
if (d == dPrev)
delete a[key-oneHourInMilliseconds];
}
return a;
},{})
console.log(Object.values(result));
An example:
let arr = [
{Date : '2020-03-21T22:00:00Z', Count: 4},
{Date : '2020-03-21T23:00:00Z', Count: 15},
{Date : '2020-03-22T00:00:00Z', Count: 66},
{Date : '2020-03-22T01:00:00Z', Count: 70},
];
const oneHourInMilliseconds = 3600000;
const result = arr.reduce((a, {Date: date, Count}) => {
let [y, m, d] = date.split(/\D+/);
let key = new Date(date).getTime();
a[key] = a[key] || { Date: date, Count };
if (a[key - oneHourInMilliseconds]) {
let [yPrev, mPrev, dPrev] = a[key - oneHourInMilliseconds].Date.split(/\D+/);
if (d == dPrev)
delete a[key-oneHourInMilliseconds];
}
return a;
},{})
console.log(Object.values(result));
var items = [
{ Date: new Date("2020-03-21T20:00:00Z"), Count: 3 },
{ Date: new Date("2020-03-21T22:00:00Z"), Count: 4 },
{ Date: new Date("2020-03-21T23:00:00Z"), Count: 15 },
{ Date: new Date("2020-03-22T00:00:00Z"), Count: 66 },
{ Date: new Date("2020-03-22T01:00:00Z"), Count: 70 },
{ Date: new Date("2020-03-22T20:00:00Z"), Count: 170 }
];
var filtered = items.filter((e, i, arr) => {
return (i == arr.length - 1 ||
arr[i].Date.toDateString() != arr[i + 1].Date.toDateString());
});
console.log(filtered);
I have the following array
const data = [
{
date: "2018-01-01",
label: "MH",
qt: 10
},
{
date: "2018-04-01",
label: "MH",
qt: 30
},
{
date: "2018-02-01",
label: "GJ",
qt: 30
},
{
date: "2018-03-01",
label: "KL",
qt: 30
},
{
date: "2018-02-01",
label: "KL",
qt: 40
}
]
and i want my output to be
[
[date,MH,GJ,KL],
['Jan 2018',10,null,null],
['Feb 2018',null,30,40],
['Mar 2018',null,null,30],
['Apr 2018',30,null,null]
]
How can i achieve that in an optimize way?
And the date should be sorted in order to.
I tried doing
data.sort(function compare(a, b) {
var dateA = new Date(a.date);
var dateB = new Date(b.date);
return dateA - dateB;
});
let labelArr = data.map(l => l.label);
let dateArr = data.map(l => l.date);
labelArr = _.uniq(labelArr);
dateArr = _.uniq(dateArr);
console.log(labelArr, dateArr);
const outputArr = [];
dateArr.forEach(d => {
labelArr.forEach(l => {
const tempObj = data.filter(r => {
if (d == r.date && l == r.label) {
return r;
}
else {
return { date: d, label: l, qt: null }
}
})
outputArr.push(tempObj);
});
});
but i'm stuck here. What I was thinking is first i'll create the objects for date and label which are not present and add thier qt to null. After that i'll group by date and then insert only the qt to the result
You could take an object for keeping the array for each date and one for keeping track of the indices of the columns.
At the end set all elements to null for not set items.
var data = [{ date: "2018-01-01", label: "MH", qt: 10 }, { date: "2018-04-01", label: "MH", qt: 30 }, { date: "2018-02-01", label: "GJ", qt: 30 }, { date: "2018-03-01", label: "KL", qt: 30 }, { date: "2018-02-01", label: "KL", qt: 40 }],
cols = {},
rows = {},
result = data
.sort(({ date: a }, { date: b }) => a > b || -(a < b))
.reduce((r, { date, label, qt }) => {
date = date.slice(0, 7);
if (!rows[date]) r.push(rows[date] = [date]);
if (!cols[label]) cols[label] = r[0].push(label) - 1;
rows[date][cols[label]] = (rows[date][cols[label]] || 0) + qt;
return r;
}, [['date']])
.map((a, _, [{ length }]) => Array.from({ length }, (_, i) => a[i] || null));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I don't know if it's the best solution, but it's a working solution:
const data = [{
date: "2018-01-01",
label: "MH",
qt: 10
},
{
date: "2018-04-01",
label: "MH",
qt: 30
},
{
date: "2018-02-01",
label: "GJ",
qt: 30
},
{
date: "2018-03-01",
label: "KL",
qt: 30
},
{
date: "2018-02-01",
label: "KL",
qt: 40
}
]
function formatData(data) {
const labels = {};
const map = {};
data
.sort((a, b) => a.date < b.date ? -1 : 1)
.forEach(item => {
const date = moment(item.date).format('MMM YYYY');
labels[item.label] = true;
if (map[date]) {
map[date][item.label] = item.qt;
} else {
map[date] = { [item.label]: item.qt };
}
});
const labelsArr = Object.keys(labels);
const formattedData = Object.keys(map).map(date => {
const values = labelsArr.map(label => map[date][label] || null);
return [date, ...values];
});
return [['date', ...labelsArr], ...formattedData];
}
const result = formatData(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://momentjs.com/downloads/moment.min.js"></script>
I tried doing this:
data.sort(function compare(a, b) {
var dateA = new Date(a.date);
var dateB = new Date(b.date);
return dateA - dateB;
});
let labelArr = data.map(l => l.label);
let dateArr = data.map(l => l.date);
labelArr = _.uniq(labelArr);
dateArr = _.uniq(dateArr);
const outputArr = [['Date', ...labelArr]];
dateArr.forEach(d => {
const o1 = data.filter(e => e.date == d)
const o2 = o1.reduce((s, a) => {
s[a.label] = a.qt;
return s;
}, {})
const b1 = []
labelArr.forEach(l => {
b1.push(o2[l])
});
outputArr.push([moment(d).format('MMM YYYY'), ...b1]);
});
Hope it helps someone.
I have an array of objects such as:
const array = [
{
date: '02-02-1994',
time: '18:00',
services: {
first: 1,
second: 1
}
},
{
date: '02-02-1994',
time: '20:00',
services: {
first: 1,
second: 1
}
},
{
date: '02-04-1994',
time: '19:00',
services: {
first: 1,
second: 1
}
},
{
date: '02-04-1994',
time: '19:00',
services: {
first: 1,
second: 2
}
}
]
I want to group it by time and date and get the result array:
const result = [{
date: '02-02-1994',
time: '18:00',
services: {
first: 1,
second: 1
}
},
{
date: '02-02-1994',
time: '20:00',
services: {
first: 1,
second: 1
}
},
{
date: '02-04-1994',
time: '19:00',
services: {
first: 2,
second: 3
}
}]
I want to group array by date then by time and to get a sum in service object.
I try to group by date using reduce, but then I don't know
You can use reduce() method to do that.
const array = [{ date: '02-02-1994', time: '18:00', services: { first: 1, second: 1 } }, { date: '02-02-1994', time: '20:00', services: { first: 1, second: 1 } }, { date: '02-04-1994', time: '19:00', services: { first: 1, second: 1 } }, { date: '02-04-1994', time: '19:00', services: { first: 1, second: 2 } } ];
let result = array.reduce((arr, currentValue) => {
let item = arr.find(item =>
item.date === currentValue.date &&
item.time === currentValue.time);
if (item) {
item.services.first += currentValue.services.first;
item.services.second += currentValue.services.second;
} else {
arr.push(currentValue);
}
return arr;
}, []);
console.log(result);
You could take a joined key for collecting items of the same group in an object and then take the values of it as result set.
var array = [{ date: '02-02-1994', time: '18:00', services: { first: 1, second: 1 } }, { date: '02-02-1994', time: '20:00', services: { first: 1, second: 1 } }, { date: '02-04-1994', time: '19:00', services: { first: 1, second: 1 } }, { date: '02-04-1994', time: '19:00', services: { first: 1, second: 2 } }],
result = Object.values(array.reduce((r, { date, time, services }) => {
var key = [date, time].join('|');
r[key] = r[key] || { date, time, services: {} };
Object
.entries(services)
.forEach(([k, v]) => r[key].services[k] = (r[key].services[k] || 0) + v);
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }