I'm working on charts in React.js and i want to display data sorted by month. In django i've created view for displaying json with total events per month and it looks like this:
[
{
"month": "2022-06-01T00:00:00+02:00",
"total": 4
},
{
"month": "2022-08-01T00:00:00+02:00",
"total": 1
}
]
]
I would like to sort every object in that array and change value 'month' from numbers to month name, so it would be:
[
{
"month": "june",
"total": 4
},
{
"month": "august",
"total": 1
}
]
]
For generating charts i'm using chartist.
You could store the full date as a seperate key (called date), and set the month in a seperate function using a predefined array for the names of each month. Here is the code you would use:
const monthName = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"]; // Array representing each month
var chartItems = [
{
"date": "2022-06-01T00:00:00+02:00",
"month": null,
"total": 4
},
{
"date": "2022-08-01T00:00:00+02:00",
"month": null,
"total": 1
}
];
// Run through each item in the array
function setMonths(arr) {
arr.forEach(item => {
const date = new Date(item.date); // Convert date string to Date object
const monthIndex = date.getMonth(); // Get index of month from the Date
const month = monthName[monthIndex]; // Convert index into text representing the month
item.month = month; // Set the month key in the object to the new month
});
}
setMonths(chartItems); // Call function to set months in the array
As an alternative, you could also make a method for each object in the array that gets the month, but you would need to run this everytime you want to get the month. Here is the code for that:
const monthName = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"];
var chartItems = [
{
"date": "2022-06-01T00:00:00+02:00",
"month": function() { return monthName[new Date(this.date).getMonth()]; },
"total": 4
},
{
"date": "2022-08-01T00:00:00+02:00",
"month": function() { return monthName[new Date(this.date).getMonth()]; },
"total": 1
}
];
And you would get it like this:
chartItems[0].month(); // "[0]", meaning the first item in the array
Related
I have an array and 2 variables. The two variables are numbers and the array contains 12 values.
const firstParam = 6;
const secondParam = 0;
originalArray = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
I want to take the numbers and check that index of the second array matches and then change the value of the matching ones.
In this case the output would be
newArray = ["blank", "February", "March", "April", "May", "June", "blank", "August", "September", "October", "November", "December"];
I was trying with map but it's not applied
const newArray = originalArray.map((element, index) => firstParam ? null : element);
How can I do it?
Is there any better way to get the desired result?
thanks for your help
You could take an array for the indices and check the index with Array#includes and return either a new value of the old value.
const
indices = [6, 0],
originalArray = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
result = originalArray.map((v, i) => indices.includes(i) ? 'blank' : v);
console.log(...result);
This question already has answers here:
Replacing objects in array
(17 answers)
Closed 3 years ago.
I'm trying to get an array from two different arrays. I'm not sure how to do it with ES6.
I want the current_year_data is replacing to previous_year_data
The First array is:
let previous_year_data = [
{ month: "January", value: 300 },
{ month: "February", value: 1 },
{ month: "March", value: 2 },
{ month: "April", value: 3 },
{ month: "May", value: 4 },
{ month: "Jun", value: 5 },
{ month: "July", value: 6 },
{ month: "August", value: 7 },
{ month: "September", value: 8 },
{ month: "October", value: 9 },
{ month: "November", value: 10 },
{ month: "December", value: 11 },
];
Second array:
let current_year_data = [
{ month: "January", value: 4459 }
];
The result should be in:
let current_year_data = [
{ month: "January", value: 4459 },
{ month: "February", value: 1 },
{ month: "March", value: 2 },
{ month: "April", value: 3 },
{ month: "May", value: 4 },
{ month: "Jun", value: 5 },
{ month: "July", value: 6 },
{ month: "August", value: 7 },
{ month: "September", value: 8 },
{ month: "October", value: 9 },
{ month: "November", value: 10 },
{ month: "December", value: 11 },
];
Thanks
It is possible to use map method. In addition, you can use Map collection to have O(1) of access to elements items when you map your array:
let unique = new Map(current_year_data.map(s=> [s.month, s.value]))
previous_year_data.map(({month, value})=> ({month, value: unique.get(month) || value }));
An example:
let previous_year_data = [
{ month: "January", value: 300 },
{ month: "February", value: 1 },
{ month: "March", value: 2 },
{ month: "April", value: 3 },
{ month: "May", value: 4 },
{ month: "Jun", value: 5 },
{ month: "July", value: 6 },
{ month: "August", value: 7 },
{ month: "September", value: 8 },
{ month: "October", value: 9 },
{ month: "November", value: 10 },
{ month: "December", value: 11 },
];
let current_year_data = [
{ month: "January", value: 4459 }
];
let unique = new Map(current_year_data.map(s=> [s.month, s.value]))
const result = previous_year_data.map(({month, value})=>
({month, value: unique.get(month) || value }));
console.log(result)
For such requirements, combine or merge JSON arrays unique by the key will work! See the following:
// Note: this will pick the last duplicated item in the list.
const previous_year_data = [
{ month: "January", value: 300 },
{ month: "February", value: 1 },
{ month: "March", value: 2 },
{ month: "April", value: 3 },
{ month: "May", value: 4 },
{ month: "Jun", value: 5 },
{ month: "July", value: 6 },
{ month: "August", value: 7 },
{ month: "September", value: 8 },
{ month: "October", value: 9 },
{ month: "November", value: 10 },
{ month: "December", value: 11 },
];
const current_year_data = [
{ month: "January", value: 4459 }
];
const key = 'month'; //Replace this key with unique key
const result = [...new Map([...previous_year_data, ...current_year_data].map(item =>
[item[key], item])).values()];
console.log(result);
/*OUTPUT
[
{
"month": "January",
"value": 4459
},
{
"month": "February",
"value": 1
},
{
"month": "March",
"value": 2
},
{
"month": "April",
"value": 3
},
{
"month": "May",
"value": 4
},
{
"month": "Jun",
"value": 5
},
{
"month": "July",
"value": 6
},
{
"month": "August",
"value": 7
},
{
"month": "September",
"value": 8
},
{
"month": "October",
"value": 9
},
{
"month": "November",
"value": 10
},
{
"month": "December",
"value": 11
}
]
*/
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 the array as below,
let yearAndMonth = [
{ "year": 2013, "month": "FEBRUARY" },
{ "year": 2015, "month": "MARCH" },
{ "year": 2013, "month": "JANUARY" },
{ "year": 2015, "month": "FEBRUARY" }
]
I want to sort the array by year first and after that sort month from the year,
I want the output like this,
yearAndMonth = [
{ "year": 2013, "month": "JANUARY " },
{ "year": 2013, "month": "FEBRUARY" },
{ "year": 2015, "month": "FEBRUARY" },
{ "year": 2015, "month": "MARCH" }
]
How to achieve this?
You could take an object for the month names and their numerical value.
The chain the order by taking the delta of year and month.
var array = [{ year: 2013, month: "FEBRUARY" }, { year: 2015, month: "MARCH" }, { year: 2013, month: "JANUARY" }, { year: 2015, month: "FEBRUARY" }];
array.sort(function (a, b) {
var MONTH = { JANUARY: 0, FEBRUARY: 1, MARCH: 2, APRIL: 3, MAY: 4, JUNE: 5, JULY: 6, AUGUST: 7, SEPTEMBER: 8, OCTOBER: 9, NOVEMBER: 10, DECEMBER: 11 };
return a.year - b.year || MONTH[a.month] - MONTH[b.month];
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can create an array for months names and sort like this:
let data = [
{ "year": 2013, "month": "FEBRUARY" }, { "year": 2015, "month": "MARCH" },
{ "year": 2013, "month": "JANUARY" }, { "year": 2015, "month": "FEBRUARY" }
];
let months = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];
data.sort(
(a, b) => (a.year - b.year) || (months.indexOf(a.month) - months.indexOf(b.month))
);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can make a map which maps the Month to the month number and then use Arrays.sort() with your own custom comparator :
let months = { 'JANUARY' : 1, 'FEBRUARY' : 2, 'MARCH' : 3, 'APRIL' : 4, 'MAY' : 5, 'JUNE' : 6, 'JULY' : 7, 'AUGUST' : 8, 'SEPTEMBER' : 9, 'OCTOBER' : 10, 'NOVEMBER' : 11, 'DECEMBER' : 12 };
let yearAndMonth = [ { "year": 2013, "month": "FEBRUARY" }, { "year": 2015, "month": "MARCH" }, { "year": 2013, "month": "JANUARY" }, { "year": 2015, "month": "FEBRUARY" } ];
yearAndMonth.sort((a,b)=> a.year - b.year || months[a.month.toUpperCase()] - months[b.month.toUpperCase()]);
console.log(yearAndMonth);
Since you are ok with using lodash this can be achived by a simple sortBy
_.sortBy(yearAndMonth, a => new Date(1+ a.month + a.year))
It will construct a new Date for each month and year (with date 1) and that should work the way you want.
let yearAndMonth = [
{ "year": 2013, "month": "FEBRUARY" },
{ "year": 2015, "month": "MARCH" },
{ "year": 2013, "month": "JANUARY" },
{ "year": 2015, "month": "FEBRUARY" }
]
let res = _.sortBy(yearAndMonth, a => new Date(1 + a.month + a.year));
console.log('Sorted Result: ', res);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Note: You do not need to have array/object/map of all the months for this to have a look up to perform > or <
You can also use lodash library for sorting data by multiple column.
I have created a demo on Stackblitz. I hope this will help/guide to you/others.
lodash - Documentation
Component.html
<table width="100%">
<tr>
<td>Year</td>
<td>Month</td>
</tr>
<tr *ngFor="let datas of sortedData">
<td>{{datas.year}}</td>
<td>{{datas.month}}</td>
</tr>
</table>
Component.ts
sortedData: any[];
data = [
{ "year": 2013, "month": "FEBRUARY" },
{ "year": 2015, "month": "MARCH" },
{ "year": 2013, "month": "JANUARY" },
{ "year": 2013, "month": "MARCH" },
{ "year": 2013, "month": "APRIL" },
{ "year": 2015, "month": "FEBRUARY" }
];
monthArray: any = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];
ngOnInit() {
this.sortedData = _.orderBy(data, [(datas) => datas.year, (user) => (this.monthArray.indexOf(user.month))], ["asc", "asc"]);
console.log(this.sortedData);
}
Declaring the month names in an array to get the relative value of the month string when comparing with each other.
First comparison will be on the year, if both the year values are same then proceeding with the month comparison based on the months array created.
let months = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];
yearAndMonth.sort((a,b) =>{
if(a.year > b.year) return 1;
else if(a.year < b.year) return -1;
else {
if(months.indexOf(a.month.toUpperCase()) >
months.indexOf(b.month.toUpperCase()))
return 1;
else if(months.indexOf(a.month.toUpperCase()) <
months.indexOf(b.month.toUpperCase()))
return -1
else return 0;
}
});
See also: JsFiddle
Allow me to provide a plain ES version (sort array of objects on 1 or more key values, serial dependant (sort on 1, sort 2 within 1, sort on 3 within 1 and 2 etc.), non mutating, i.e. keep the original array as is):
const log = (...str) =>
document.querySelector("pre").textContent += `${str.join("\n")}\n`;
const data = getData();
const xSort = XSort();
const months = [ "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" ];
log( JSON.stringify(
xSort
.create(data)
.orderBy( {key: "year"}, { key: v => months.indexOf(v.month) } ),
null,
" ")
);
function XSort() {
const multiSorter = sortKeys => {
if (!sortKeys || sortKeys[0].constructor !== Object) {
throw new TypeError("Provide at least one {key: [keyname]} to sort on");
}
return function (val0, val1) {
for (let sortKey of sortKeys) {
const v0 = sortKey.key instanceof Function ? sortKey.key(val0) : val0[sortKey.key];
const v1 = sortKey.key instanceof Function ? sortKey.key(val1) : val1[sortKey.key];
const isString = v0.constructor === String || v1.constructor === String;
const compare = sortKey.descending ?
isString ? v1.toLowerCase().localeCompare(v0.toLowerCase()) : v1 - v0 :
isString ? v0.toLowerCase().localeCompare(v1.toLowerCase()) : v0 - v1;
if (compare !== 0) {
return compare;
}
}
};
}
const Sorter = function (array) {
this.array = array;
};
Sorter.prototype = {
orderBy: function(...sortOns) {
return this.array.slice().sort(multiSorter(sortOns));
},
};
return {
create: array => new Sorter(array)
};
}
function getData() {
return [{
"year": 2013,
"month": "FEBRUARY",
},
{
"year": 2015,
"month": "MARCH",
},
{
"year": 2015,
"month": "SEPTEMBER",
},
{
"year": 2013,
"month": "JANUARY",
},
{
"year": 2013,
"month": "MARCH",
},
{
"year": 2013,
"month": "APRIL",
},
{
"year": 2015,
"month": "FEBRUARY",
}
];
}
<pre></pre>
Github: Bootstrap Daterangepicker, plugin source: daterangepicker.js
I want to set global values for the locale option. I don't want to set it for each element every time I use it.
Here is an example code how to setup daterangepicker for a specific element.
$('#demo').daterangepicker({
"locale": {
"format": "MM/DD/YYYY",
"separator": " - ",
"applyLabel": "Apply",
"cancelLabel": "Cancel",
"fromLabel": "From",
"toLabel": "To",
"customRangeLabel": "Custom",
"weekLabel": "W",
"daysOfWeek": [
"Su",
"Mo",
"Tu",
"We",
"Th",
"Fr",
"Sa"
],
"monthNames": [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
],
"firstDay": 1
},
"startDate": "12/01/2016",
"endDate": "12/07/2016"
}, function(start, end, label) {
console.log("New date range selected: ' + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD') + ' (predefined range: ' + label + ')");
});
Is it even possible? Or do I have to rewrite the plugin?
What's the best approach if this is not possible without some custom modification?
you can store the dateRangePickerSettings as a global variable
var dateRangePickerSettings = {
locale: {...},
};
and reference it to all ur plugin instances
$('#demo1').daterangepicker({
"locale": dateRangePickerSettings.locale,
"startDate": "06/01/2016",
"endDate": "06/07/2016"
});
$('#demo2').daterangepicker({
"locale": dateRangePickerSettings.locale,
"startDate": "12/01/2016",
"endDate": "12/07/2016"
});
Dan Grossman added support in 2.1.26
Added support for $.fn.daterangepicker.defaultOptions to set default options for all pickers on page.
Lets try to explain it here for newcomers.
$.fn.daterangepicker.defaultOptions = {
locale: {
"format": "DD/MM/YYYY",
"separator": " - ",
"applyLabel": "Aplicar",
"cancelLabel": "Cancelar",
"fromLabel": "Desde",
"toLabel": "Hasta",
"customRangeLabel": "Personalizado",
"weekLabel": "W",
"firstDay": 0,
"daysOfWeek": ["Lu","Ma","Mi","Ju","Vi","Sa","Do"],
"monthNames": [
"Enero",
"Febrero",
"Marzo",
"Abril",
"Mayo",
"Junio",
"Julio",
"Agosto",
"Septiembre",
"Octubre",
"Noviembre",
"Diciembre",
]
}
}
$('#period').daterangepicker();
Thanks to #kurdemol94
I am making a dropdown using this component
https://github.com/fraserxu/react-dropdown
I am calling it like this:
<Dropdown options={monthOptions} onChange={this.changeMonth} value={defaultMonth} placeholder="Select Month" />
Using this data:
export const monthOptions = [
"January", "February", "March", "April", "May",
"June", "July", "August", "September", "October", "November", "December"
];
export const defaultMonth = "January";
And this method:
changeMonth: function(option) {
this.setState({month: option});
},
However, when I display the component in the browser, it is unresponsive. It doesn't show any options:
There is no message printed in the console.