Sorting nested arrays of objects by date - javascript

I'm trying to sort an array that looks like this:
var dateGroups = [
[
{age:20, date: Fri Feb 03 2012 14:30:00 GMT+1100 (EST)},
{age:12, date: Fri Feb 03 2012 18:20:00 GMT+1100 (EST)},
{age:18, date: Fri Feb 03 2012 21:43:00 GMT+1100 (EST)}
],
[
{age:32, date: Fri Feb 01 2012 10:54:00 GMT+1100 (EST)},
{age:44, date: Fri Feb 01 2012 11:45:00 GMT+1100 (EST)},
],
[
{age:22, date: Fri Feb 05 2012 10:54:00 GMT+1100 (EST)},
{age:22, date: Fri Feb 05 2012 18:22:00 GMT+1100 (EST)},
]
]
The objects inside dateGroups' nested arrays are already sorted in ascending order, but I also want to sort the arrays themselves based on the grouped dates.
In this case the array should then look like this:
var dateGroups = [
[
{age:32, date: Fri Feb 01 2012 10:54:00 GMT+1100 (EST)},
{age:44, date: Fri Feb 01 2012 11:45:00 GMT+1100 (EST)},
],
[
{age:20, date: Fri Feb 03 2012 14:30:00 GMT+1100 (EST)},
{age:12, date: Fri Feb 03 2012 18:20:00 GMT+1100 (EST)},
{age:18, date: Fri Feb 03 2012 21:43:00 GMT+1100 (EST)}
],
[
{age:22, date: Fri Feb 05 2012 10:54:00 GMT+1100 (EST)},
{age:22, date: Fri Feb 05 2012 18:22:00 GMT+1100 (EST)},
]
]
The function used to sort should also return the new sorted version of dateGroups.
I've tried using Underscore.js's sortBy() function but I can't figure out how to sort the arrays based on the value of a property inside one of the objects. Is there a specific way to sort Date objects? Or are they sorted in the same way as numbers or letters?

According to Underscore.js documentation, you should simply write your own iterator for that cause. Something like this:
_.sortBy(dateGroups, function(arrayElement) {
//element will be each array, so we just return a date from first element in it
return arrayElement[0].date.getTime();
});

You can sort them by passing a custom sort function to Array.sort.
dateGroups.sort(function(a, b) {
return b[0].date.getTime() - a[0].date.getTime();
});
The custom function needs to return a number less than zero (a comes before b), greater than zero (a comes after b) or zero (a and b are equal).

As far as I understand your question, you want to sort the inner groups so that the early dates will be displayed first and then sort the groups by their first dates.
This could be done like this:
var sortedDateGroups = dateGroups.map(function(dateGroup) {
// sort the inner groups
dateGroup.sort(function(a,b) {
return a.date.getTime() - b.date.getTime();
});
return dateGroup;
}).sort(function(a,b) {
// sort the outer groups
return a[0].date.getTime() - b[0].date.getTime();
});
Of course this could be done with underscore js in a similar fashion:
var sortedDateGroups = _.chain(dateGroups).map(function(dateGroup) {
return _.sortBy(dateGroup, function(inner) {
return inner.date.getTime();
});
}).sortBy(function(outer) {
return outer[0].date.getTime();
}).value()

In case you have dates in string format, this worked for me:
yourArray.sort((a, b) => Date.parse(b[3]) - Date.parse(a[3]))

Related

How do I split an array with multiple elements to get the last item in JavaScript?

I apologize if this question is too simple, I am just getting started in JavaScript. I have the following problem:
A function is returning an array similar to:
[
"Wed Feb 24 11:39:01 CST 2021",
"Thu Mar 21 18:35:30 CDT 2019",
"Tue Feb 26 15:23:50 CST 2019"
]
My challenge is to grab just the year from each of those elements within the array (so I need to grab 2021, 2019, and 2019).
I was thinking in my head to use .split by using space as the delimitator and then using length-1 to get the last element. But my implementation keeps throwing errors.
I tried:
var fromDate = $dateList[*].dates
var fromDateSplit = fromDate.split(' ');
var fromYear = fromDateSplit[fromDateSplit.length - 1]
Please let me know what I am doing wrong. Getting ready to pull hair out.
Thank you in advance for looking at this!
Simply split it by spaces and get the last item in the result array:
const a = [
"Wed Feb 24 11:39:01 CST 2021",
"Thu Mar 21 18:35:30 CDT 2019",
"Tue Feb 26 15:23:50 CST 2019"
]
const b = a.map(e => e.split(" ").slice(-1)[0]);
console.log(b);
My challenge is to grab just the year from each of those elements
within the array (so I need to grab 2021, 2019, and 2019).
With a simple loop and new Date(v).getFullYear().
const arr = [
"Wed Feb 24 11:39:01 CST 2021",
"Thu Mar 21 18:35:30 CDT 2019",
"Tue Feb 26 15:23:50 CST 2019"
]
console.log(arr.map(v => new Date(v).getFullYear()))
Keep your hair on your head and follow me:
On second line, your variable 'fromDateSplit' is trying to split an array, not a string. The split method belongs to string objects. So, you can try iterate over your array and apply the split on the current element of the iteration. Like this:
var array = [
"Wed Feb 24 11:39:01 CST 2021",
"Thu Mar 21 18:35:30 CDT 2019",
"Tue Feb 26 15:23:50 CST 2019"
]
array.forEach(element => {
var fromDateSplit = element.split(' ');
var fromYear = fromDateSplit[fromDateSplit.length - 1];
console.log(fromYear);
});
You could also look for the last space in the strings using string.lastIndexOf(" "), and take what comes afterwards.
const a = [
"Wed Feb 24 11:39:01 CST 2021",
"Thu Mar 21 18:35:30 CDT 2019",
"Tue Feb 26 15:23:50 CST 2019"
]
const years = a.map((e) => e.substring(e.lastIndexOf(" ")));
console.log(years);

Google Chart - arrayToDataTable not an array error

I have a backend in nodejs that generates an array and call a javascript function to plot a graph.
var data = google.visualization.arrayToDataTable(value)
The problem that I got a uncaught error:
Printing the variable value I have:
[ [ 'ml', 'date' ],
[ 'Sun Nov 24 2019 13:30:00 GMT-0200 (Brasilia Summer Time)',
481 ],
[ 'Sun Nov 24 2019 14:00:00 GMT-0200 (Brasilia Summer Time)',
571 ] ]
Reading similar posts like Google Chart - uncaught error: not an array i tried:
var data = google.visualization.arrayToDataTable(JSON.parse(values));
But i get the following error:
If I hardcode values it works fine:
var values = google.visualization.arrayToDataTable([
['ml','date'],
['Sun Nov 24 2019 13:30:00 GMT-0200 (Brasilia Summer Time)',481 ],
['Sun Nov 24 2019 14:00:00 GMT-0200 (Brasilia Summer Time)',571 ]
]);
var data = google.visualization.arrayToDataTable(values);
I couldn't see any difference printing the variable from hardcoding.
Any ideia?
the array is most likely being passed as a string.
if so, you need to use --> JSON.parse
but you need to swap the single quotes (') for double quotes (")
see following snippet, which works...
var test = JSON.parse('[["ml","date"],["Sun Nov 24 2019 13:30:00 GMT-0200 (Brasilia Summer Time)",481 ],["Sun Nov 24 2019 14:00:00 GMT-0200 (Brasilia Summer Time)",571 ]]');
console.log(test);
while this snippet does not...
var test = JSON.parse("[['ml','date'],['Sun Nov 24 2019 13:30:00 GMT-0200 (Brasilia Summer Time)',481 ],['Sun Nov 24 2019 14:00:00 GMT-0200 (Brasilia Summer Time)',571 ]]");
console.log(test);

How to sort Date on NeDb Database with JavaScript

How can I sort Dates like below in a NeDb Database with a JavaScript function?
This sort command in the function loaddata() does not work:
loaddata() {
this.$db.DBData.find({}).sort({ pubDate: 1 }).exec((err, docs) => {
this.Data = docs;
});
}
Examples for pubDate:
Fri, 29 Jun 2018 20:15:00 +0200
Mon, 25 Jun 2018 04:22:00 +0200
Fri, 29 Jun 2018 05:10:00 +0200
Sat, 30 Jun 2018 23:35:43 +0200
Thanks in advance!
If the dates are being stored as strings then sorting them as strings is going to be alphabetizing them by the short day. If you convert them to Date objects before sorting it should work:
loaddata() {
this.$db.DBData.find({}).exec((err, docs) => {
let newDocs = docs.map((doc)=>{
doc.pubDate = new Date(doc.puDate).valueOf();
});
newDocs.sort((a, b)=>{
return a.pubDate - b.pubDate; //you may have to switch the order
});
this.Data = newDocs;
});
}
Another solution would be to save the Date value instead of the string representation. For example the dates you gave above translate to:
[1530296100000, 1529893320000, 1530241800000, 1530394543000]
Then sorting them results in:
[1529893320000, 1530241800000, 1530296100000, 1530394543000]
Converted back that's:
["Sun Jun 24 2018 22:22:00 GMT-0400 (Eastern Daylight Time)",
"Thu Jun 28 2018 23:10:00 GMT-0400 (Eastern Daylight Time)",
"Fri Jun 29 2018 14:15:00 GMT-0400 (Eastern Daylight Time)",
"Sat Jun 30 2018 17:35:43 GMT-0400 (Eastern Daylight Time)"]
You can see how they are sorted in order now and back in their string representation. Sorry for the time zone conversion I ran this example in the console on my browser to make sure it works.
Harry Chilinguerian's answer is on the right track, but remember to return the document inside the map function. For my solution, I decided to keep the original date and instead create a different property to store the date value. Finally, I think most users would prefer reverse chronological ordering:
loaddata() {
this.$db.DBData.find({}).exec((err, docs) => {
let newDocs = docs.map((doc)=>{
doc.pubDateValue = new Date(doc.pubDate).valueOf(); // new property
return doc; // return the new document
});
newDocs.sort((a, b)=>{
return b.pubDateValue - a.pubDateValue; // reverse chronological order
});
this.Data = newDocs;
});
}

Javascript loop and insert new object

I with ajax get this data:
[{"id":125,"price":225,"start":"Tue, 26 Apr 2016 00:00:00 +0000","user_id":8},{"id":124,"price":200,"start":"Wed, 27 Apr 2016 00:00:00 +0000","user_id":8},{"id":121,"price":67,"start":"Sat, 23 Apr 2016 00:00:00 +0000","user_id":8},{"id":114,"price":45,"start":"Sun, 08 May 2016 00:00:00 +0000","user_id":9},{"id":113,"price":55,"start":"Sun, 24 Apr 2016 00:00:00 +0000","user_id":8},{"id":111,"price":55,"start":"Wed, 01 Jun 2016 00:00:00 +0000","user_id":11},{"id":110,"price":53,"start":"Fri, 03 Jun 2016 00:00:00 +0000","user_id":8},{"id":107,"price":53,"start":"Wed, 03 Aug 2016 00:00:00 +0000","user_id":8},{"id":106,"price":55,"start":"Mon, 01 Aug 2016 00:00:00 +0000","user_id":8},{"id":105,"price":53,"start":"Tue, 16 Aug 2016 00:00:00 +0000","user_id":8},{"id":104,"price":55,"start":"Thu, 21 Apr 2016 00:00:00 +0000","user_id":11},{"id":101,"price":57,"start":"Wed, 17 Aug 2016 00:00:00 +0000","user_id":8}]
so as you can see there is start data.
I also have:
var start = '04/17/2016 12:00 am';
var end = '09/20/2016 12:01 am';
Now I need to make loop day by day from start to end, check if day(date) excist into json and if not add new data into json :
{"id":0,"price":100,"start":"DATE","user_id":0}
What is the best way to do that?
UPDATE:
I create one new with dates from start to end but now I need to put json into new array: http://jsbin.com/qekijumobe/edit?js,output
My another answer had a fault in there, this is what I came up after it:
First, create a foreach loop, wich loops trough all of the objects inside the array
for (var obj of objArray) {} //Use "of" instead of "in" tk get the values and not the indices
Then, inside this loop, check every field of the objects, if they're the same, abd if they're, then break out the loop, else, if there's no matching object, push it in the array.
function isInArray(yourObj) {
for (var obj of objArray) {
if (obj.id == yourObj.id && obj.start == yourObj.start && obj.price == yourObj.price && obj.user_id == yourObj.user_id)
return true;
}
return false;
}

How to compare dates to see where adjacent times meet?

I have dates currently formatted in the following way:
[ [ Tue Jun 17 2014 09:00:00 GMT-0400 (EDT),
Tue Jun 17 2014 10:00:00 GMT-0400 (EDT) ] ]
[ [ Thu Jun 19 2014 09:30:00 GMT-0400 (EDT),
Thu Jun 19 2014 11:30:00 GMT-0400 (EDT) ] ]
[ [ Tue Jun 17 2014 10:00:00 GMT-0400 (EDT),
Tue Jun 17 2014 11:00:00 GMT-0400 (EDT) ] ]
These dates are actually "sessions", and I need to see where certain sessions are adjacent to each other. For example, in this specific case, the first array of dates has a end time of 10AM while the last array of dates has a start time for 10AM. How can I computationally find this situation?
The one approach I have is to first sort the array sets from earliest time to to latest time, and then compare each of the start/end date pairs to see if they are the same, but I can't seem to get it through. Any ideas are welcome!
Turn the strings into Unix timestamps with Date.parse() (if these are actually Date objects, then use the .getTime() method) and then order the sessions with Array.prototype.sort(). Here's an example where the sessions are ordered by start time:
var sessions = [
["Tue Jun 17 2014 09:00:00 GMT-0400 (EDT)", "Tue Jun 17 2014 10:00:00 GMT-0400 (EDT)"],
["Thu Jun 19 2014 09:30:00 GMT-0400 (EDT)", "Thu Jun 19 2014 11:30:00 GMT-0400 (EDT)"],
["Tue Jun 17 2014 10:00:00 GMT-0400 (EDT)", "Tue Jun 17 2014 11:00:00 GMT-0400 (EDT)"]
];
for (var i = 0; i < sessions.length; i++) {
sessions[i].startTime= Date.parse(sessions[i][0]);
}
sessions.sort(function(a, b) { return a.startTime-b.startTime; });

Categories

Resources