I'm struggling with sorting two levels. The logic is as follows. If any of the objects have a status, return the most recent object with a status. If none of the objects have a status, return the most recent object without a status.
var apps = [
{ status: 'PASS',
date_created: Thu Sep 03 2015 17:24:45 GMT-0700 (PDT)
},
{ status: 'FAIL',
date_created: Thu Sep 02 2015 17:24:45 GMT-0700 (PDT),
},
{ status: '',
date_created: Thu Sep 03 2015 17:24:45 GMT-0700 (PDT),
}
]
var desired_result = [{ status: 'PASS',
date_created: Thu Sep 03 2015 17:24:45 GMT-0700 (PDT)
}]
var apps_2 = [
{ status: '',
date_created: Thu Sep 03 2015 17:24:45 GMT-0700 (PDT)
},
{ status: '',
date_created: Thu Sep 02 2015 17:24:45 GMT-0700 (PDT),
},
{ status: '',
date_created: Thu Sep 01 2015 17:24:45 GMT-0700 (PDT),
}
]
var desired_resul2 = [{ status: '',
date_created: Thu Sep 03 2015 17:24:45 GMT-0700 (PDT)
}]
I've tried
var sorted = _.sort_by(apps, function (x) { x.date_updated });
I've also looked a few other SO questions but can't keep the objects in place after the first sort.
If I understand your question correctly, here is what you are looking for. http://jsfiddle.net/whxu5sea/3/
You need to filter the elements to ensure they have a status of ANY kind. Then sort them by date, earliest first. Then get that first value. In my example I assumed the dates where strings, but still should work.
var apps = [
{ status: 'PASS',
date_created: 'Thu Sep 03 2015 17:24:45 GMT-0700 (PDT)'
},
{ status: 'FAIL',
date_created: 'Thu Sep 02 2015 17:24:45 GMT-0700 (PDT)',
},
{ status: '',
date_created: 'Thu Sep 01 2015 17:24:45 GMT-0700 (PDT)',
}
];
var x;
var arr = _.filter(apps, function(data) {
return !!data.status.length;
});
x = _.chain( arr.length ? arr : apps )
.sortBy(function(data) {
return new Date(data.date_created).getTime();
}).last().value();
console.log( x );
To check if it works when no status is provided: http://jsfiddle.net/whxu5sea/4/
I hope this helps. LMK if any further clarification is needed.
EDIT: Updated to get NEWEST element (last).
Here is a simple solution that iterates just once through apps, without a filtering step. See here for a jsfiddle.
The concept is that, if status is falsy, its date is converted into a negative number that retains the correct sort order among all falsy elements, but makes all falsy elements have a lower sort order than all non-falsy ones.
We convert the falsy element dates by subtracting 8640000000000001, which is (the maximimum millis in a Date, plus one).
var x = _.chain(apps).sortBy(function(x) {
var date = new Date(x.date_created).getTime();
return x.status ? date : date - 8640000000000001;
}).last().value();
console.log( x );
Related
Let me start off by apologizing for the length of this post but I want to be as verbose as possible as this issue is very interesting and weird.
I am rendering a date picker with room availability for resorts that my company manages. This is accomplished with two functions (one back end function and one front end function).
The back end function makes a request to an external API, formats the response into an array of date objects and returns the array.
The front end function calls the back end function and then pushes the response onto an object that renders the availability.
The array of date objects is not changed or mutated in any way after it is formatted by the back end function. Yet somehow the dates that are rendered on the front end are always one day before the date that is returned from the back end function.
I know that sounds confusing so let me clarify.
Here is the array of date objects that is returned from the back end function:
correct dates
Here is what is rendered to the date picker:
Incorrect dates
At first I was almost convinced that the date picker was just getting the dates wrong so I did a bit more digging and found out that the dates that are stored in the array are somehow changing as they are being passed back to the front end function.
Here is the code for the front end function that is applicable:
getAvailAsync(startDate, endDate, attributeId, resortId, room, resort, duration).then(response => {
console.log("returned to front end", response.res.availability)
response.res.error ? "" : repeaterData.push(response.res)
$w("#resortsRepeater").data = repeaterData
if(repeaterData.length > 12) {
$w("#loadMore").show()
}
if(repeaterData.length > 0) {
$w("#loadingStrip").collapse()
}
})
Here is what is logged to the console from the front end:
[
{
"startDate": "Fri Jul 15 2022 17:00:00 GMT-0700 (Pacific Daylight Time)",
"endDate": "Fri Jul 15 2022 17:00:00 GMT-0700 (Pacific Daylight Time)"
},
{
"startDate": "Sat Jul 16 2022 17:00:00 GMT-0700 (Pacific Daylight Time)",
"endDate": "Sat Jul 16 2022 17:00:00 GMT-0700 (Pacific Daylight Time)"
},
{
"startDate": "Sun Jul 17 2022 17:00:00 GMT-0700 (Pacific Daylight Time)",
"endDate": "Sun Jul 17 2022 17:00:00 GMT-0700 (Pacific Daylight Time)"
},
{
"startDate": "Mon Jul 18 2022 17:00:00 GMT-0700 (Pacific Daylight Time)",
"endDate": "Mon Jul 18 2022 17:00:00 GMT-0700 (Pacific Daylight Time)"
},
{
"startDate": "Tue Jul 19 2022 17:00:00 GMT-0700 (Pacific Daylight Time)",
"endDate": "Tue Jul 19 2022 17:00:00 GMT-0700 (Pacific Daylight Time)"
},
{
"startDate": "Tue Jul 26 2022 17:00:00 GMT-0700 (Pacific Daylight Time)",
"endDate": "Tue Jul 26 2022 17:00:00 GMT-0700 (Pacific Daylight Time)"
}
]
As you can see the first date is July 15th and the last date is July 26th.
Now here is the applicable code from the back end getAvailAsync function:
if(validAvail == undefined) {
resolve({ res: {error: "No availability found"}})
} else {
console.log("Valid avail before passing to the front end", validAvail)
validAvail.length > 0
?
resolve({
res: {
...resortInfo,
...roomInfo,
availability: validAvail
}
})
: resolve({
res: {error: "No availability found"}
})
}
Here is what is logged to the console from the back end function:
[
{
"startDate": "2022-07-16T00:00:00.000Z",
"endDate": "2022-07-16T00:00:00.000Z"
},
{
"startDate": "2022-07-17T00:00:00.000Z",
"endDate": "2022-07-17T00:00:00.000Z"
},
{
"startDate": "2022-07-18T00:00:00.000Z",
"endDate": "2022-07-18T00:00:00.000Z"
},
{
"startDate": "2022-07-19T00:00:00.000Z",
"endDate": "2022-07-19T00:00:00.000Z"
},
{
"startDate": "2022-07-20T00:00:00.000Z",
"endDate": "2022-07-20T00:00:00.000Z"
},
{
"startDate": "2022-07-27T00:00:00.000Z",
"endDate": "2022-07-27T00:00:00.000Z"
}
]
As you can see the first date is July 16th and the last date is July 27th.
What's more is every single date has been decremented by 1 somehow.
I am completely clueless as to why this is happening. The only thing that I can think of is that the back end function has a date object for the start date and end date after being returned from the API (see the first image where it says {"startDate": {$date: "2022-07-02...}, ...}
Could that somehow be messing up the date? And if so how do I resolve this?
As pilchard mentioned this issue was related to the changing of time zones when the date object was passed to the front end and rendered to the screen. I just had to set the hour manually to noon using date.setHours(). This way the date was not changed when the timezone changed.
I'm referring to this answer again.
var firstEvents = events.reduce(function(ar, e) {
var id = e.getId();
if (e.isRecurringEvent() && e.isAllDayEvent() && !ar.some(function(f) {return f.eventId == id})) {
ar.push({eventTitle: e.getTitle(), eventId: id, startDate: e.getAllDayStartDate(), endDate: e.getAllDayEndDate()});
}
return ar;
}, []);
What do I have to change to get an array with the event titles (Strings) as keys and the start dates (Date objects) as values so I can retrieve a certain start date (Date object) via firstEvents['some event title']?
EDIT:
Current Ouput:
firstEvents = [{eventTitle=Event title 1, eventId=xyz1#google.com, startDate=Sun Mar 18 00:00:00 GMT+01:00 2018, endDate=Mon Mar 19 00:00:00 GMT+01:00 2018},
{eventTitle=Event title 2, eventId=xyz2#google.com, startDate=Tue Mar 19 00:00:00 GMT+01:00 2019, endDate=Wed Mar 20 00:00:00 GMT+01:00 2019},
{eventTitle=Event title 3, eventId=xyz3#google.com, startDate=Fri Mar 20 00:00:00 GMT+01:00 2020, endDate=Sat Mar 21 00:00:00 GMT+01:00 2020}]
Needed Output (Pseudo):
firstEvents = ['Event title 1' => Sun Mar 18 00:00:00 GMT+01:00 2018,
'Event title 2' => Tue Mar 19 00:00:00 GMT+01:00 2019,
'Event title 3' => Fri Mar 20 00:00:00 GMT+01:00 2020]
Do not use push, but set to object with key.
ar = {}; // You may need to change source parameter too
// you cannot change input Array [] to Object {} type inside function
// you can get Array and return Object, but source variable will not change
ar[e.getTitle()] = e.getAllDayStartDate();
Or using some demo data:
var ar = [
{
eventTitle: 'one',
eventId: '#1',
startDate: new Date(),
endDate: new Date()
},
{
eventTitle: 'two',
eventId: 'secondId',
startDate: new Date(),
endDate: new Date()
}];
var retVal = {};
for (var i of ar) {
retVal[i.eventId] = i;
}
console.log(JSON.stringify(retVal, null, 2));
console.log(retVal['#1']);
console.log(retVal.secondId);
This is my Array
$scope.tooltipsArray = [
{
date: 2018-10-10T07:03:43.835Z,
text: 'name1'
},
{
date: 2018-09-29T18:30:00.000Z,
text: 'name2'
}
];
How can I update date to locale date format like this.
$scope.tooltipsArray = [
{
date: Wed Oct 10 2018 14:05:27 GMT+0530 (India Standard Time),
text: 'name1'
},
{
date: Sun Sep 30 2018 00:00:00 GMT+0530 (India Standard Time),
text: 'name2'
}
];
I have used map() to do that. But it does not work
var vector = $scope.tooltipsArray.map(function (el) { return new Date(el.date).toLocaleDateString(); });
Can anyone tell me how to do this from map() in JavaScript?
You can use the below code -
$scope.tooltipsArray = [
{
date: "2018-10-10T07:03:43.835Z",
text: 'name1'
},
{
date: "2018-09-29T18:30:00.000Z",
text: 'name2'
}
];
var vector = $scope.tooltipsArray.map(function(el) {return { 'date':new Date(el.date).toString(),'text':el.text}});
console.log(vector);
The output will be like below -
[
{date: "Wed Oct 10 2018 12:33:43 GMT+0530 (India Standard Time)", text: "name1"}
{date: "Sun Sep 30 2018 00:00:00 GMT+0530 (India Standard Time)", text: "name2"}
]
Why is there a .value key after tooltipsArray?
You assigned the array to tooltipsArray, so unless there's a Proxy involved, expect to access the array through $scope.tooltipsArray.
To fix it, just remove .value.
var vector = $scope.tooltipsArray.map(function (el) { return new Date(el.date).toLocaleDateString(); });
1- Remove .value why is there in the first place?
2- You need to change the date inside the object and then return el instead of date if you just want the date to be changed, likewise:
var vector = $scope.tooltipsArray.map(function(el) {
el.date = new Date(el.date).toLocaleDateString();
return el;
});
What map function does is going through array element one by one and run the callback function, so what you have to do is update the whole object or update one entry
el.date = new Date(el.date).toLocaleDateString();
I have a JSON object like so:
{
"Sat Jul 28 2018 03:36:36 GMT-0700 (Pacific Daylight Time)":[
{ ... },
{ ... }
],
"Fri Aug 03 2018 19:07:14 GMT-0700 (Pacific Daylight Time)":[
{ ... }
],
"Sat Aug 18 2018 17:25:50 GMT-0700 (Pacific Daylight Time)":[
{ ... }
]
}
How can I return this into a grouped object by month?
Try this (with lodash):
var input = {
"Sat Jul 28 2018 03:36:36 GMT-0700 (Pacific Daylight Time)": [
"test", "tester"
],
"Fri Aug 03 2018 19:07:14 GMT-0700 (Pacific Daylight Time)": [
"tester1"
],
"Sat Aug 18 2018 17:25:50 GMT-0700 (Pacific Daylight Time)": [
"tester2"
]
}
var groupedKeys = _.groupBy(Object.keys(input), function(key) {
return key.substring(4, 7)
});
var groupedEntries = _.map(groupedKeys, (values, key) => {
values = _.map(values, (value) => {
return input[value]
});
return {
key: key,
values: _.flattenDeep(values)
};
});
var result = _.reduce(groupedEntries, (result, obj) => {
result[obj.key] = obj.values;
return result;
}, {})
console.log(result);
Output:
{
"Jul": [
"test",
"tester"
],
"Aug": [
"tester1",
"tester2"
]
}
Loop through the object then extract month and create new object:
let jsonObj = {
"Sat Jul 28 2018 03:36:36 GMT-0700 (Pacific Daylight Time)":[{},{}],
"Fri Aug 03 2018 19:07:14 GMT-0700 (Pacific Daylight Time)":[{}],
"Sat Aug 18 2018 17:25:50 GMT-0700 (Pacific Daylight Time)":[{}]
};
let grouped = Object.keys(jsonObj).reduce((prev,key,i,all)=>{
let monthArr = {};
if(typeof prev === 'string'){
monthArr[prev.substr(4,3)] = jsonObj[prev];
prev = {};
}
monthArr[key.substr(4,3)] = jsonObj[key];
return {...prev,...monthArr};
});
This question already has answers here:
How to get value at a specific index of array In JavaScript?
(8 answers)
Closed 4 years ago.
I have an array of object :
this.things=[
{
id:XYZ,
event: Fri Jul 20 2018 15:00:04 GMT+0200 (CEST)
person: 3
}, {
person: 4
id:XYZ1,
event: Fri Jul 10 2018 15:00:04 GMT+0200 (CEST)
}, {
id:XYZ2,
person: 5
event: Fri Aug 20 2018 15:00:04 GMT+0200 (CEST)
}
]
I only want to get the first event value like this.
event: Fri Jul 20 2018 15:00:04 GMT+0200 (CEST)
tried this
this.things[Object.keys(this.things)[0]['event']]
unfortunately not working.
You don't need to use Object.keys here.
this.things[0]['event']
or
this.things[0].event
this.things = [
{
id: 'XYZ',
event: 'Fri Jul 20 2018 15:00:04 GMT+0200 (CEST)',
person: '3'
}, {
person: 4,
id: 'XYZ1',
event: 'Fri Jul 10 2018 15:00:04 GMT+0200 (CEST)',
}, {
id: 'XYZ2',
person: '5 ',
event: 'Fri Aug 20 2018 15:00:04 GMT+0200 (CEST)',
}
]
var i = 0;
document.getElementById("demo").innerHTML = this.things[i].event
Clear your Array object error ","
<h1 id="demo"></h1>