How to group an array of objects by month & year? [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have an array of objects like so:
entries: [
{
id:1,
text: "Lorem ipsum",
timeStamp:"Thu, 01 Jun 2018"
},
{
id:3,
text:"Lorem ipsum",
timeStamp:"Thu, 24 May 2018"
},
{
id:4,
text: "Lorem ipsum",
timeStamp:"Thu, 24 May 2018"
}
]
Now I'd like to be able to group them into an 'archive' array like so:
archive: [
{
monthyear: May 2018,
entries: 2
},
{
monthyear: June 2018,
entries: 5
}
]
Wondering what sort of array functions should I use to get the intended result.

You could use reduce method to group array items by date and toLocaleString method to get month and year.
const data = [{"id":1,"text":"Lorem ipsum","timeStamp":"Thu, 01 Jun 2018"},{"id":3,"text":"Lorem ipsum","timeStamp":"Thu, 24 May 2018"},{"id":4,"text":"Lorem ipsum","timeStamp":"Thu, 24 May 2018"}]
const result = data.reduce((r, {timeStamp}) => {
let dateObj = new Date(timeStamp);
let monthyear = dateObj.toLocaleString("en-us", { month: "long", year: 'numeric' });
if(!r[monthyear]) r[monthyear] = {monthyear, entries: 1}
else r[monthyear].entries++;
return r;
}, {})
console.log(Object.values(result))

Related

How to convert array1 to array2? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I need data structure like mokeData2 and sources data was like mokeData.
How can I convert mokeData to mokeData2 in javascript?
const mokeData = ["Friday 07:07:00", "Sunday 12:05:00"];
const mokeData2 = [{ Friday: "07:07:00", Sunday: "12:05:00" }];
1) You can easily achieve the result using Object.fromEntries and map
const mokeData = ["Friday 07:07:00", "Sunday 12:05:00"];
const mokeData2 = [{ Friday: "07:07:00", Sunday: "12:05:00" }];
const result = [Object.fromEntries(mokeData.map((s) => s.split(" ")))];
console.log(result);
2) You can also use reduce here as:
const mokeData = ["Friday 07:07:00", "Sunday 12:05:00"];
const mokeData2 = [{ Friday: "07:07:00", Sunday: "12:05:00" }];
const result = [
mokeData.reduce((acc, curr) => {
const [key, value] = curr.split(" ");
acc[key] = value;
return acc;
}, {}),
];
console.log(result);

Get date ranges [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have an array of objects -
[
{ name:'abc',
lRange: '2020-01-01',
hRange: '2020-01-22',
},
{ name:'abc',
lRange: '2020-01-01',
hRange: '2020-01-22',
},
{ name:'def',
lRange: '2020-01-15',
hRange: '2020-01-30',
},
{ name:'ghi',
lRange: '2020-02-10',
hRange: '2020-02-22',
}
]
I need to get the min Date and Max Date range combining all the dates lRange and hRange dates - there will be a overlap of the dates too.
I have tried sorting by date times but that is not giving me the correct range. any ideaS?
Here's one way to do it, though I suspect there are more elegant methods. It converts each string date into a date object and compares them. Finally it takes the min and max and converts them back into readable strings.
let dates = [{
name: 'abc',
lRange: '2019-02-01',
hRange: '2020-01-22',
},
{
name: 'abc',
lRange: '2020-01-01',
hRange: '2020-01-22',
},
{
name: 'def',
lRange: '2020-01-15',
hRange: '2020-01-30',
},
{
name: 'ghi',
lRange: '2020-02-10',
hRange: '2020-02-22',
}
]
let output = {}
dates.forEach(obj => {
if (!output.min) {
output.min = new Date(obj.lRange);
output.max = new Date(obj.hRange);
} else {
output.min = Math.min(output.min, new Date(obj.lRange))
output.max = Math.max(output.max, new Date(obj.hRange))
}
})
//convert back to date strings
output.min = new Date(output.min).toISOString().split("T")[0]
output.max = new Date(output.max).toISOString().split("T")[0]
console.log(output)
You can use flatMap to get all dates and then sort it. After sorting the first element (i.e element at index 0) is minRange and element at last index is maxRange.
const arr = [
{ name: "abc", lRange: "2020-01-01", hRange: "2020-01-22" },
{ name: "abc", lRange: "2020-01-01", hRange: "2020-01-22" },
{ name: "def", lRange: "2020-01-15", hRange: "2020-01-30" },
{ name: "ghi", lRange: "2020-02-10", hRange: "2020-02-22" },
];
const sortedResult = arr
.flatMap((obj) => [obj.lRange, obj.hRange])
.sort((a, b) => new Date(a) - new Date(b));
const result = {
min: sortedResult[0],
max: sortedResult[sortedResult.length - 1],
};
console.log(result);
You can pull the lRagnes and hRanges out into individual arrays if it makes it easier for you.
var lDates = [];
var hDates = [];
yourArray.map((innerObjects) => {
lDates .push(innerObjects.lRange);
hDates .push(innerObjects.hRange);
});

Summarize data in array of objects by common date [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
This is my data,
"time" is number
[
{
"time": 202007150800,
"count": 10
},
{
"time": 202007160700,
"count": 11
},
{
"time": 202007160900,
"count": 12
}
]
How do I use "time" group data from 8 o'clock yesterday to 8 o'clock today and sum "count"
,For example, 7/15 data is 7/15 08:00 - 7/16 07:00
like this:
[
{
"time": 20200715,
"count": 21
},
{
"time": 20200716,
"count": 12
}
]
Try this function
function mapData(data) {
let result = [];
data.forEach(element => {
let t = element.time + 9200;
let substr = t.toString().substr(0, 8);
if(!result[substr])
result[substr] = 0;
result[substr] += element.count;
});
let returnResult = [];
result.forEach((element, index) =>
returnResult.push({
time: index,
count: element
})
);
return returnResult;
}

Combine objects of an array with the same date into one - JavaScript

I receive an array of posts through an API and want to merge the ones with the same "month" and "year" (day is not important), into one object. I looked up for answers but there are just too many foo-bar examples that confuses more than helping. I want to know the cleanest, most elegant way of handling such problems, without getting into call-back hell and nested blocks...
Here is the API response:
0:
{
date: {day: 27, month: 1, year: 2020}
id: 3
}
1:
{
date: {day: 28, month: 1, year: 2020}
id: 4
}
2:
{
date: {day: 31, month: 1, year: 2020}
id: 5
}
3:
{
date: {day: 1, month: 2, year: 2020}
id: 6
}
4:
{
date: {day: 2, month: 2, year: 2020}
id: 7
}
The expected outcome:
0:
result: {month: 1, year: 2020, id:[3,4,5]}
1:
result: {month: 2, year: 2020, id:[6,7]}
One approach would be to use the Array#reduce() method to transform the input array into a dictionary, where each value contains the accumulation of id's for that month and year. Once this dictionary has been built, you could then extract the values of that dictionary to an array via Object#values() to obtain the required output:
let input=[{date:{day:27,month:1,year:2020},id:3},{date:{day:28,month:1,year:2020},id:4},{date:{day:31,month:1,year:2020},id:5},{date:{day:1,month:2,year:2020},id:6},{date:{day:2,month:2,year:2020},id:7}];
/* Convert the dictionary that will be created by reduce to a value array */
var output = Object.values(input.reduce((dict, item) => {
const { date, id } = item;
/* The distinct key for this item based on month/year of date field */
const key = `${date.month}-${date.year}`;
/* Check if dictionary already has an object value for key. This short hand
will only insert a new object value for key, if one does not already exist
in the dictionary */
const value = dict[key] || { month : date.month, year : date.year, id : [] };
/* Add the item id to the dictionary entries id array */
value.id.push(id);
/* Update value object for key */
return { ...dict, [key] : value };
}, {}))
console.log(output);
The idea here is that the dictionary is built using Compound Keys, where the keys are derived from the month and year of the current array item.
When no value exists for the current key, a new value object is inserted to the dictionary for that key:
{ month : date.month, year : date.year, id : [] }
The id of the current array item is then added (accumulated) to the id sub array of the object for that key:
dict[key].id.push(id);
Hope that helps
Here is an alternate approach, if you are not a big fan of Array.reduce and Array.values and also, if you like to consider performance when running the response for a larger data set.
This approach avoids cloning object (or rather non-mutating object) with spread operator i.e {...<anyObject>} while iterating. which should be fine for minimal set of data but but definitely not when you deal with huge volume.
const response = [{
date: { day: 27, month: 1, year: 2020 },
id: 3
}, {
date: { day: 28, month: 1, year: 2020 },
id: 4
}, {
date: { day: 31, month: 1, year: 2020 },
id: 5
},{
date: { day: 1, month: 2, year: 2020 },
id: 6
},{
date: { day: 2, month: 2, year: 2020 },
id: 7
}];
function groupByMonthYear(response) {
// output
const groupedData = []
// Using map for lookup to avoid iterating again on the grouped data
const referenceMap = new Map();
// destructing month, year and id from the response
for (const { date: { month, year }, id } of response) {
const groupKey = `${month}${year}`
// check if the month and year reference is already seen using the groupKey MMYYYY
if (referenceMap.has(groupKey)) {
referenceMap.get(groupKey).id.push(id);
// early return
continue;
}
// simply add a new entry if it doesn't exist
const data = {
month,
year,
id: [id]
};
groupedData.push(data);
referenceMap.set(groupKey, data)
}
return groupedData;
}
// Invoke and Print the result
console.log(groupByMonthYear(response));

How to get the sum of values per day grouped by day from an array in JS? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
In JS, given an array of objects, like:
[{
date: 1525655429184,
value: 20.00
},{
date: 1525655429184,
value: 3.99
},{
date: 1526001029184,
value: 19.00
},{
date: 1526001025184,
value: 4.30
}]
Where the 'date' property is a date in milliseconds, and the 'value' property is a monetary represented by a float, and each object of this array can be one day of the month with his associated value.
I want to get the sum of value for each week day, to show in a chart of total values x day.
So the output should be like this example:
[
{ day: 'Sun', sum: 23.99 },
{ day: 'Mon', sum: 0 },
{ day: 'Tue', sum: 22.2 },
{ day: 'Wed', sum: 22.3 },
{ day: 'Thu', sum: 2.2 },
{ day: 'Fri', sum: 32.2 },
{ day: 'Sat', sum: 22.43 },
]
First, you need to convert the date (which i believe in milliseconds) into date and get the day by using getDay(). Create an array of days, loop thru the days, and if the converted date is the same as the day sum the values. Take a look at the snippet below.
var data = [{
date: 1525655429184,
value: 20.00
}, {
date: 1525655429184,
value: 3.99
}, {
date: 1526001029184,
value: 19.00
}, {
date: 1526001025184,
value: 4.30
}]
var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
var sumVals = [];
var daysSum = [];
var sumVal = days.forEach(function(day) {
var total = 0;
data.forEach(function(items) {
var d = new Date(items.date);
var formattedD = days[d.getDay()];
if (day === formattedD) {
total += parseFloat(items.value);
}
})
sumVals.push(total)
daysSum.push([day, total])
})
console.log(days)
console.log(sumVals)
console.log(daysSum)//just to show if it matches
Milliseconds in a day:
var millsperday = 1000*60*60*24;
Current millisecond/day offset:
var d = new Date();
var m = d.getTime();
d.setHours(0,0,0,0);
var o = d.getTime()-m;
So, to divide a list of (unixtime) milliseconds:
for (i=0;i<list.length;i++) {
numberofday = Math.floor((list[i]-o)/millsperday) ;
}

Categories