Reputation: 11
My array is like this:
const myArray = [{
date: "2017-01-01",
Name: "test1"
},
{
date: "2017-01-02",
Name: "test2"
},
{
date: "2017-02-04",
Name: "test3"
},
{
date: "2017-02-05",
Name: "test3"
}
]
I want to convert this into:
const myArray = [{
group: "Jan",
data: [{
date: "2017-01-01",
Name: "test1"
},
{
date: "2017-01-02",
Name: "test2"
}
]
},
{
group: "Feb",
data: [{
date: "2017-02-04",
Name: "test3"
},
{
date: "2017-02-05",
Name: "test3"
}
]
}
]
Upvotes: 1
Views: 114
Reputation: 24648
You can use Object.entries()
, Array#reduce
, and Array#map
methods as follows*:
const
myArray = [ { date: "2017-01-01", Name: "test1" }, { date: "2017-01-02", Name: "test2" }, { date: "2017-02-04", Name: "test3" }, { date: "2017-02-05", Name: "test3" } ],
month = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
outArr = Object.entries(
myArray.reduce(
(acc,{date,Name,group = month[+date.split('-')[1] - 1]}) =>
({ ...acc, [group]:[...(acc[group] || []),{date,Name}] }), {}
)
)
.map(([group,data]) => ({group,data}));
console.log( outArr );
NOTE
I wonder why new Date(
2017-01-01).toLocaleString('default',{month:'short'})
thinks the date is Sat Dec 31, 2016
, hence giving Dec
instead of Jan
. There may be a bug in the Date object; if the date is in the format mm-dd-yyyy it works fine but with yyyy-mm-dd the object always subtracts one day.
Alternatively ....
Working with mm-dd-yyyy format would work as expected at least here where this is the default date format:
const
myArray = [ { date: "2017-01-01", Name: "test1" }, { date: "2017-01-02", Name: "test2" }, { date: "2017-02-04", Name: "test3" }, { date: "2017-02-05", Name: "test3" } ],
outArr = Object.entries(
myArray.reduce(
(acc,{date,Name,d = date.split('-'),group = new Date([d[1],d[2],d[0]].join('-')).toLocaleString('default',{month:'short'})}) =>
({ ...acc, [group]:[...(acc[group] || []),{date,Name}] }), {}
)
)
.map(([group,data]) => ({group,data}));
console.log( outArr );
Upvotes: 1
Reputation: 1590
assuming the date
inside myArray
is always yyyy-MM-dd
then my solution should work just fine.
const myArray = [{
date: "2017-01-01",
Name: "test1"
},
{
date: "2017-01-02",
Name: "test2"
},
{
date: "2017-02-04",
Name: "test3"
},
{
date: "2017-02-05",
Name: "test3"
}
]
const result = myArray.reduce((p,c)=>{
const monthOfData = new Date(c.date).toLocaleString('default', { month: 'short' });
const found = p.findIndex(p => p.group === monthOfData);
if(found !==-1){
p[found].data.push(c);
} else {
p.push({
group: monthOfData,
data:[c]
})
}
return p;
}, []);
console.log(result);
Or, @danh's suggestion, using an object to build the index and taking a second pass to re-form into the desired output...
const myArray = [
{date: "2017-01-01", Name: "test1"},
{date: "2017-01-02", Name: "test2"},
{date: "2017-02-04", Name: "test3"},
{date: "2017-02-05", Name: "test3"} ]
// reduce into an object. keys are unique and O(1) lookup
const byDate = myArray.reduce((p, c) => {
const monthOfData = new Date(c.date).toLocaleString('default', { month: 'short' });
p[monthOfData] ??= []
p[monthOfData].push(c)
return p;
}, {});
// re-form to match the output
const result = Object.keys(byDate).map(d => {
return { group: d, data: byDate[d] }
})
console.log(result)
for the additional question, for grouping by year and month.
const myArray = [
{ date: "2021-11-01", Name: "example1" },
{ date: "2021-12-01", Name: "example2" },
{ date: "2022-02-01", Name: "example3" },
{ date: "2022-02-02", Name: "example4" },
{ date: "2023-05-22", Name: "example5" }
]
const result = myArray.reduce((p, c) => {
const [monthOfData, yearOfData] = new Date(c.date).toLocaleString("default", { month: "short", year: "numeric" }).split(" ");
p[yearOfData] ??= {};
p[yearOfData][monthOfData] ??= [];
p[yearOfData][monthOfData].push(c);
return p
}, {});
console.log(result);
Upvotes: 1
Reputation: 99
Hope you will get help from the below sample code.
Here TestA should be a class whose content date and name attributes.
HashMap<String, List<TestA>> map = new HashMap<>();
for (TestA testA: myArray){
String month = monthName(testA.getDate());
if(!map.containsKey(month)){
map.put(month, new ArrayList<>());
}
map.get(month).add(testA);
}
public String monthName(String date){
try {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
calendar.setTime(sdf.parse(date));
return new DateFormatSymbols().getMonths()[calendar.get(Calendar.MONTH)];
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
Thanks
Upvotes: 0