sort array of objects by property in object - javascript

I have an array of objects like:
[
{date: "2016-01-07T15:01:51+00:00", text: "Lorem ipsum"},
{date: "2016-22-08T15:04:36+00:00", text: "dolor"},
// etc.
]
How's the best way to sort these by the date property? I'm already mapping this array to a react component, so any solution that works within the map function I guess would be preferred, but not essential.
I'm trying to use the sort() method at the moment, but can't work how to feed it the date property.

You can have a custom sort function:
var data = [{
date: "2016-07-01T15:01:51+00:00",
text: "Lorem ipsum"
}, {
date: "2016-02-22T15:04:36+00:00",
text: "dolor"
}, {
date: "2015-08-22T15:04:36+00:00",
text: "test"
}]
var result = data.sort(function(a, b) {
var date1 = new Date(a.date);
var date2 = new Date(b.date);
console.log(date1, date2);
return (+date1 - +date2);
});
console.log(result)

Related

JavaScript array.sort doesn't work on Array of Objects

For some reason I can't sort my Array of Objects using Sort Function:
FullHistory.sort(function(a, b){
return a.Date.localeCompare(b.Date);
});
When I use console.log() - It returns: -1/0/1, but the Array's Order is not changing at all
The rest of my Code:
let FullHistory = [];
CurrentTitle = $(data).find(".normal_header").text().replace(" Episode Details", "");
$($(data).find('.spaceit_pad').get().reverse()).each(function () {
FullHistory.push({ Title: CurrentTitle, Ep: $(this).text().replace("Ep ", "").split(',')[0], Date: $(this).append(":00").text().replace("Ep ", "").replace("watched", "").replace(" Remove", "").split(",")[1].replace("on ", "").replace("at ", "").replace(" ", "") });
});
I tried: changing let to var, using if statements in Sort Function, changing types, using Lodash Lib.
Your Date properties will be sorted as strings -- that is what localeCompare does. It doesn't look at those strings as representing dates. Since the date format used is not ISO, the lexical order of those strings does match the order you would expect for the dates.
So convert the strings to numerical epochs:
let FullHistory = [
{Title: "Grand Blue", Ep: "1", Date: "02/19/2020 23:36:00" },
{Title: "Darling in the FranXX", Ep: "1", Date: "03/04/2019 23:44:00" },
];
FullHistory.sort(function(a, b){
return Date.parse(a.Date) - Date.parse(b.Date);
});
console.log(FullHistory);

How to create a json grouped by date in js?

I have an array of objects sorted by date:
const alerts = [{
id: 1, date: '2018-10-31T23:18:31.000Z', name: 'Joke', title: 'this is the first 1'
}, {
id: 2, date: '2018-10-30T23:18:31.000Z', name: 'Mark', title: 'this is the second one'
}]
I am trying to 'group' the alerts by date so trying to create 'datesections' which have a dateheader, the result should be something like:
const sections = [{
date: '2018-10-31T23:18:31.000Z',
heading: 'today',
alerts: [{ id: 1, date: '2018-10-31T23:18:31.000Z', name: 'Joke',
title: 'this is the first one' }]
}, {
date: '2018-10-30T23:18:31.000Z',
heading: 'Yesterday',
alerts: [{ id: 2, date: '2018-05-30T23:18:31.000Z', name: 'Mark',
title: 'this is the second one' }]
}]
I tried something this but can't figure out how to get the alerts with the same date in the alerts prop:
const sections2=alerts.map(a =>
({
date: a.date,
heading:'today new',
alerts:alerts
})
)
const alerts = [
{ id: 1, date: '2018-10-31T23:18:31.000Z', name: 'Joke', title: 'this is the first 1' },
{ id: 2, date: '2018-05-30T23:18:31.000Z', name: 'Mark', title: 'this is the second one' }
]
const grouping = _.groupBy(alerts, element => element.date.substring(0, 10))
const sections = _.map(grouping, (items, date) => ({
date: date,
alerts: items
}));
console.log(sections);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Can't help you with headings - what if it's neither "today" or "yesterday"?
I feel like you are asking a couple of things here. The key one is how to group by day with a date.
To do that you will first need to know how to group. This answer may help with that.
As far as how to group by day there are a number of ways to do that. Simplest I can think of is to cut off everything after the "T" in the date string and sort that.
From my point of view it's not really a map what you need here, map will return a new array but not what you want. You can do this with 2 for statements
let total = [];
for (let j = 0; j < alerts.length; j++) {
let item = alerts[j];
let foundDate = false;
for (let i = 0; i < total.length; i++) {
if (total[i].date === item.date) {
foundDate = true;
total.alerts.push(item);
}
}
if (!foundDate) {
console.log("!found");
total.push({
date: item.date,
heading: "Yesterday",
alerts: [item]
});
}
}
If you console.log yout total array, will contain what you want.
If you need any other explanation pls let me know.
You can use a regular expression to match the part of the date you want and then group your data. You can add there the header you want. Hope this helps.
const alerts = [
{ id: 1, date: '2018-10-31T23:18:31.000Z', name: 'Joke', title: 'this is the first 1' },
{ id: 2, date: '2018-10-30T23:18:31.000Z', name: 'Mark', title: 'this is the second one' },
{ id: 3, date: '2018-10-30T23:14:32.000Z', name: 'Mark', title: 'this is the third one' }
];
const groupByDate = (data) => {
return data.reduce((acc, val) => {
const date = val.date.match(/\d{4}-\d{2}-\d{2}/g).toString();
const item = acc.find((item) => item.date.match(new RegExp(date, 'g')));
if (!item) acc.push({ date: val.date, alerts: [val], heading: 'some heading' });
else item.alerts.push(val);
return acc;
}, []);
};
console.log(groupByDate(alerts));
Maybe you need something like this? Didn't have much time for this and last array parsing might be done in more elegant way ;)
var alerts = [
{ id: 1, date: '2018-10-31T23:18:31.000Z', name: 'Joke', title: 'this is the first 1' },
{ id: 3, date: '2018-10-31T23:44:31.000Z', name: 'Joke1', title: 'this is the 2nd' },
{ id: 2, date: '2018-10-30T23:18:31.000Z', name: 'Mark', title: 'this is the second one' },
{ id: 4, date: '2018-10-30T23:45:31.000Z', name: 'Mark1', title: 'this is the 3rd' },
{ id: 5, date: '2018-10-27T23:18:31.000Z', name: 'Mark2', title: 'this is the 4th' },
];
var processedAlerts = [], finalAlerts;
(function(initAlerts){
//iterate through array to make keys to group by day
for(var i = 0; i < initAlerts.length; i++){
processedAlerts[i] = initAlerts[i];
//substring here can be more sophisticated - this was faster
initAlerts[i].keyDate = initAlerts[i].date.substr(0, 10);
}
//supporting function to convert string to date
//to acheve more detailed sorting that includes time
//just use date object and use hours, minutes and/or seconds to create Date object
function dateFromString(strDate){
var date, tmpDate;
//convert string to array - I assume that date format is always the same
//yyyy-mm-dd and will become Array 0: year, 1: month, 2: day of the month
tmpDate = strDate.split("-");
//moths in js are zero pased so Jan is 0, Feb is 1 and so on
//so we want to substract 1 from human readable month value to get correct date
date = new Date(tmpDate[0], tmpDate[1]-1, tmpDate[2]);
return date;
}
//function used to compare dates and passed to sort function
function comparedates(obj1, obj2){
var date1, date2;
date1 = dateFromString(obj1.keyDate);
date2 = dateFromString(obj2.keyDate);
let comparison = 0;
if(date1>date2){
comparison = 1;
} else if(date1<date2){
comparison = -1;
}
//to achieve reverse just multiply comparison result by -1
return comparison*(-1);
}
function getHeader(date){
//here place logic to generate header
//this involves comparing dates probably from keyDate
return "temp header: " + date.toString()
}
//sort the array by keyDate from newest to oldest
processedAlerts.sort(comparedates);
//final array rebuild
//pass here sorted array
finalAlerts = (function(arrayAlerts){
var aAlerts = [], k = 0;
for(var j = 0; j < arrayAlerts.length; j++){
//check if entry for date exists
//if no than create it
if(!aAlerts[k]){
aAlerts[k] = {
//removed title because I asummed that each alert has unique title and put them in alerts instead
date: arrayAlerts[j].keyDate, //agroupped date
heading: getHeader(arrayAlerts[j].keyDate), //update this function to return personalized heading
//here you can shape the alert object how you need
//I just passed it as it was
alerts: [arrayAlerts[j]] //array with first object inside
};
} else {
//add another alert to day
aAlerts[k].alerts.push(arrayAlerts[j]) //array with first object inside
}
//increasing final array key
//if there is previous entry and keys are the same for current and previous
if(arrayAlerts[j-1] && (arrayAlerts[j].keyDate == arrayAlerts[j-1].keyDate)){
k++;
}
}
return aAlerts;
})(processedAlerts);
})(alerts);
console.log(finalAlerts);

how to do sorting in moment.js by newest and oldest?

my array is like this:
const myArr = [{text: 'Hello', created: '2018-05-22T08:56:42.491Z'}, {text: 'Hello', created: '2018-05-24T05:56:42.491Z'},]
with this kind of array, I want to sort them by newest and oldest, this is my current implementation which does not work:
if (sortFilter === 'oldest') {
contactData = contactData.sort(({ created: prev }, { created: next }) => moment(prev).format('L') - moment(next).format('L'));
} else if (sortFilter === 'newest') {
contactData = contactData.sort(({ created: prev }, { created: next }) => moment(next).format('L') - moment(prev).format('L'));
}
what's wrong with my code?
Without using momentjs, you can use sort() and use new Date() and convert string to date object.
Newest first.
const myArr = [{
text: 'Hello',
created: '2018-05-22T08:56:42.491Z'
}, {
text: 'Hello',
created: '2018-05-24T05:56:42.491Z'
}, ];
myArr.sort((a,b)=> new Date(b.created).getTime() - new Date(a.created).getTime());
console.log(myArr);
Oldest First:
const myArr = [{
text: 'Hello',
created: '2018-05-22T08:56:42.491Z'
}, {
text: 'Hello',
created: '2018-05-24T05:56:42.491Z'
}, ];
myArr.sort((a, b) => new Date(a.created).getTime() - new Date(b.created).getTime());
console.log(myArr);
You have ISO 8601 date string which is built to sort lexicographically.
let myArr = [{text: 'Hello', created: '2018-05-22T08:56:42.491Z'}, {text: 'Hello', created: '2018-05-24T05:56:42.491Z'}];
myArr.sort((a,b) => a.created.localeCompare(b.created));
console.log(myArr);

How do you create Object of Arrays in Javascript

I spent more time on this than I would like to admit. I have trouble constructing an object filled with an array.
I would like my data to look like this:
items={
{
'2012-05-22': [{text: 'item 1 - any js object'}],
'2012-05-23': [{text: 'item 2 - any js object'}],
'2012-05-24': [],
'2012-05-25': [{text: 'item 3 - any js object'},{text: 'any js object'}],
}
}
I am making a database call and the data I receive looks like this:
Object {start: "08:00:00", end: "09:00:00", full_name: "Tomomi", date: "2017-06-08", Barber_id: "1"…}
The data I am interested in is the full_name value and the date value.
This is what I have attempted:
let newItems = {};
axios.post(endpoint, {lookup: day.dateString}).then((customerData) => {
customerData.data.forEach((val,key)=>{
newItems = {[val.date]:[]};
newItems[val.date].push({name:val.full_name});
console.log(newItems);
})
}
It looks like this:
Object {2017-06-08: Array(1)}
2017-06-08
:
Array(1)
This is very close, but the problem is that my code is overwriting my data.
I am trying to create this dynamically:
'2012-05-25': [{text: 'item 3 - any js object'},{text: 'any js object'}],
So that each date can have many users. Hopefully, this makes sense.
Thanks for any help.
The function expression you pass to forEach has this as the first line:
newItems = {[val.date]:[]};
This resets the newItems object to an object with one date:name pair. You really want something more like:
newItems[val.date]?newItems[val.date].push({name:val.full_name}):newItems[val.date]=[];
var byDate = {}; // Object to store received data by-date
function addIntoByDate( obj ) {
byDate[obj.date] = byDate[obj.date] || [];
byDate[obj.date].push( obj );
}
// Simulate adding server data one by one
addIntoByDate( {date: "2017-06-08", full_name: "Cat", text:"Foo!!"} ); // < SAME DATE
addIntoByDate( {date: "2016-05-23", full_name: "Dog", text:"Bar"} );
addIntoByDate( {date: "2017-06-08", full_name: "Bug", text:"Baz..."} ); // < SAME DATE
// test
console.dir(byDate);
You can use object destructuring, computed property and Object.assign()
const newItems = {};
const data = [
{
start: "08:00:00"
, end: "09:00:00"
, full_name: "Tomomi"
, date: "2017-06-08"
, Barber_id: "1"
}
];
data.forEach(({date, full_name}) =>
Object.assign(newItems, {[date]: [{/* text: */ full_name}]}));
console.log(newItems);

concatenate string to json object

I am trying to use mustache with a bootstrap calendar called Bic_Calendar
basically you can add events to the calendar with an object like this
var events = [
{
date: "28/10/2013",
title: 'DUE DAY ENROLMENT',
},
{
date: "29/10/2013",
title: 'DUE DAY PAYMENT',
},
{
date: "31/10/2013",
title: '1st DAY OF CLASS',
},
]
;
what I want is using mustache to have a quick summary of the next events, the problem is that in order to mustache render the
template the object needs to be change to:
var events = {"events": [
{
date: "28/10/2013",
title: 'DUE DAY ENROLMENT',
},
{
date: "29/10/2013",
title: 'DUE DAY PAYMENT',
},
{
date: "31/10/2013",
title: '1st DAY OF CLASS',
},
]}
;
so I am trying to concatenate the original event into a new one but it is not working, so i guess i am doing something wrong in the concatenation
var events1 = '{"events": '. concat(events) .concat('}');
var events1 = '{"events": ' + events + '}';
non of this options works!
var events is not JSON. It is a literal javascript array, you should not be concatenating it, but simply nesting it in a new object and then serializing into JSON if you need a JSON string.
var events = [
{
date: "28/10/2013",
title: 'DUE DAY ENROLMENT',
},
{
date: "29/10/2013",
title: 'DUE DAY PAYMENT',
},
{
date: "31/10/2013",
title: '1st DAY OF CLASS',
},
];
var nestedEvents = { 'events': events };
var jsonEvents = JSON.stringify(nestedEvents);
As a general rule of thumb, if you find yourself tempted to manually build a JSON string, you are probably not taking the right approach. Build the data structure you want to serialize into JSON first, then serialize it.
The other takeaway, which seems to be a common point of confusion for developers, is that JSON is nothing more than a serialized string representation of some data structure. There is no such thing as a JSON object. The JSON format certainly bears a strong resemblance to a javascript object literal, but it is truly different and should be treated as such. In this case your events variable does not contain a JSON string, so you should not expect to be able to concatenate it as if it were a string.
You have an array of objects like
var events = [
{
date: "28/10/2013",
title: 'DUE DAY ENROLMENT',
},
{
date: "29/10/2013",
title: 'DUE DAY PAYMENT',
},
{
date: "31/10/2013",
title: '1st DAY OF CLASS',
}
];
Just make a new object with your event array like this
var eventsObj = { 'events': events };
If you need to make it a json string then you may use JSON.stringify, which will convert an object to json string. BTW, concat is array objects' method.

Categories

Resources