Unfortunately I have again problems with my grouped messages. I have already received a lot of help from you, so I feel a bit embarrassed to ask again - but I'm not getting ahead with this.
My first goal was to group messages by their created_date. Thanks to your help this works very well now. Now I have tried to output the grouped messages, but it does not work. I slowly don't understand the whole thing anymore...
I want to output the group key (date) first and then every single message in each group. This is what I’ve tried:
jQuery(document).ready(function ($) {
let messages = [{
sender_id: "0",
message: "Test",
created_at: "Thu Mar 12 2020 17:26:23 GMT+0100 (Mitteleuropäische Normalzeit)"
}, {
sender_id: "0",
message: "Hallo",
created_at: "Thu Mar 12 2020 17:26:23 GMT+0100 (Mitteleuropäische Normalzeit)"
}];
let groupedMessages = [];
$(messages).each(function (index, message) {
let createdAtDate = new Date(message["created_at"]).toLocaleDateString(navigator.language, {
day: "2-digit",
month: "2-digit",
year: "numeric"
});
if (typeof groupedMessages[createdAtDate] === "undefined") {
groupedMessages[createdAtDate] = [];
}
groupedMessages[createdAtDate].push(message);
});
console.log(groupedMessages);
if (groupedMessages && groupedMessages.length > 0) {
$(groupedMessages).each(function (index, messages) {
console.log(index); //Expected output: 12.03.2020
$(messages).each(function (index, message) {
console.log(message["sender_id"]);
console.log(message["message"]);
console.log(message["created_at"]);
})
});
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
The issue is because of this line
let groupedMessages = []
You are setting groupedMessages as an array when it should be an object. array's don't have keys in JavaScript, which is why you get no output.
jQuery(document).ready(function ($) {
let messages = [{
sender_id: "0",
message: "Test",
created_at: "Thu Mar 12 2020 17:26:23 GMT+0100 (Mitteleuropäische Normalzeit)"
}, {
sender_id: "0",
message: "Hallo",
created_at: "Thu Mar 12 2020 17:26:23 GMT+0100 (Mitteleuropäische Normalzeit)"
}];
let groupedMessages = {};
$(messages).each(function (index, message) {
let createdAtDate = new Date(message["created_at"]).toLocaleDateString(navigator.language, {
day: "2-digit",
month: "2-digit",
year: "numeric"
});
if (typeof groupedMessages[createdAtDate] === "undefined") {
groupedMessages[createdAtDate] = [];
}
groupedMessages[createdAtDate].push(message);
});
console.log(groupedMessages);
if (groupedMessages && groupedMessages.length > 0) {
$(groupedMessages).each(function (index, messages) {
console.log(index); //Expected output: 12.03.2020
$(messages).each(function (index, message) {
console.log(message["sender_id"]);
console.log(message["message"]);
console.log(message["created_at"]);
})
});
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
To solve your problem I would suggest you such things:
You can`t use string keys for arrays, use objects in case you want to have string keys
Do not use $().each... because it iterates over jQuery collections, instead use built in js functions of $.each to iterate over js object or array.
Check solution below
jQuery(document).ready(function ($) {
let messages = [{
sender_id: "0",
message: "Test",
created_at: "Thu Mar 12 2020 17:26:23 GMT+0100 (Mitteleuropäische Normalzeit)"
}, {
sender_id: "0",
message: "Hallo",
created_at: "Thu Mar 12 2020 17:26:23 GMT+0100 (Mitteleuropäische Normalzeit)"
}];
let groupedMessages = {};
messages.forEach(function (message, index) {
let createdAtDate = new Date(message["created_at"]).toLocaleDateString(navigator.language, {
day: "2-digit",
month: "2-digit",
year: "numeric"
});
if (typeof groupedMessages[createdAtDate] === "undefined") {
groupedMessages[createdAtDate] = [];
}
groupedMessages[createdAtDate].push(message);
});
console.log(groupedMessages);
if (Object.keys(groupedMessages).length)
{
Object.keys(groupedMessages).map(date => {
console.log(date); //Expected output: 12.03.2020
groupedMessages[date].map(message => {
console.log(message["sender_id"]);
console.log(message["message"]);
console.log(message["created_at"]);
})
});
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Related
I had posted this question earlier but someone deleted with How can I access and process nested objects, arrays or JSON?
as possible answer. This is not helping me since a) The key 'date' is spread across several names, b)The objects comprises on arrays & objects & c) The depth at which the key 'date' is present can change.
Hence posting the question again.
I have a JS object as below
const bb = {
Harry: {
details: [
{
cat: "Life",
values: [
{
date: "2021-08-02",
level: 77.6,
},
{
date: "2021-08-03",
level: 79.1,
},
],
},
],
},
Barry: {
details: [
{
cat: "Logic",
values: [
{
date: "2021-08-02",
level: 77.6,
},
{
date: "2021-08-03",
level: 79.1,
},
],
},
],
},
};
I also have a variable defined for parsing the dates const dateParse = d3.timeParse("%Y-%m-%d")
I want to parse all the dates in the object. Since the 'date' is few levels below in the object, I am not able to figure this out. How do I go about it?
The expected output is
const bb = {
Harry: {
details: [
{
cat: "Life",
values: [
{
date: Mon Aug 02 2021 00:00:00 GMT+0530 (India Standard Time),
level: 77.6,
},
{
date: Tue Aug 03 2021 00:00:00 GMT+0530 (India Standard Time),
level: 79.1,
},
],
},
],
},
Barry: {
details: [
{
cat: "Logic",
values: [
{
date: Mon Aug 02 2021 00:00:00 GMT+0530 (India Standard Time),
level: 77.6,
},
{
date: Tue Aug 03 2021 00:00:00 GMT+0530 (India Standard Time),
level: 79.1,
},
],
},
],
},
};
You just have to loop through the objects, select the date node and execute
(new Date(datestring)).toString()
This will generate the date as specified in your output.
const bb = { Harry: { details: [{cat: "Life",values: [{date: "2021-08-02",level: 77.6},{date: "2021-08-03",level: 79.1}]}]},Barry: {details: [{cat: "Logic",values: [{date: "2021-08-02",level: 77.6},{date: "2021-08-03",level: 79.1}]}]}};
Object.values(bb).forEach((value) => {
value.details.forEach((detail) => {
detail.values.forEach((value) => {
value.date = (new Date(value.date)).toString();
})
})
});
console.log(bb);
If you want to parse all the nested date keys, you can do it recursively using the below functions
const bb = { Harry: { details: [{cat: "Life",values: [{date: "2021-08-02",level: 77.6},{date: "2021-08-03",level: 79.1}]}]},Barry: {details: [{cat: "Logic",values: [{date: "2021-08-02",level: 77.6},{date: "2021-08-03",level: 79.1}]}]}};
function traverseArray(inputArray) {
for (const arrayValue of inputArray) {
traverseObject(arrayValue);
}
}
function traverseObject(inputObject) {
for (const key in inputObject) {
const value = inputObject[key];
const valueType = typeof(value);
if (valueType == "object") {
traverseObject(value);
} else if (valueType == "array") {
traverseArray(value);
} else if (key == "date") { // since I want to parse only date keys
inputObject[key] = 'd3.timeParse("%Y-%m-%d") - Parse date here';
}
}
}
traverseObject(bb);
console.log(bb);
I have two arrays of objects:
\\offers
[
{DeskUID: "B11A13", Day: 06 Jun 2020}
{DeskUID: "B11A13", Day: 07 Jun 2020}
{DeskUID: "B12B34", Day: 23 Jun 2020}
]
\\reservations
[
{DeskUID: "B11A13", Day: 06 Jun 2020, Name: "Mike"}
{DeskUID: "B12B34", Day: 23 Jun 2020, Name: "Ali"}
]
I would like to have a result where are available offers, that means only the offers without already reserved desks.
\\result
[
{DeskUID: "B11A13", Day: 07 Jun 2020}
]
How to get the difference between two arrays of objects in JavaScript
I already tried solutions on the link above but without success, I just got a result array as sum of all objects from the two arrays.
function comparer(otherArray){
return function(current){
var reserveDay = new Date (current.Day)
return otherArray.filter(function(other){
var offerDay = new Date (other.Day)
return other.DeskUID == current.DeskUID && offerDay == reserveDay
}).length == 0;
}
}
var onlyInA = offers.filter(comparer(reservations));
var onlyInB = reservations.filter(comparer(offers));
result = onlyInA.concat(onlyInB);
You can do in a single function, like:
const available = offers.filter(offer => {
return reservations.findIndex(reservation => reservation.DeskUID === offer.DeskUID && sameDay(new Date(reservation.Day), new Date(offer.Day))) === -1;
});
function sameDay(d1, d2) {
return (
d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate()
);
}
console.log(available);
So, what is exactly happening...
offers.filter runs a check for each element in the offers array.
reservations.findIndex will try to find if there is already a reservation for that offer. It does by going into the reservations array and checking if there is the same unique ID and same date for the offer that is currently filtering.
If the result is equal to -1 it means that there is no reservation for that offer. Therefore it is available.
I've used the dates as string for the sake of simplicity, you can just alter to Date object. Hope it helps!
EDIT
I've added a small helper function for you to compare if the dates are from the same day. You can check this answer for a more detailed explanation: how to tell if two dates are in the same day?
You could take a Set and filter the reservations.
var getKey = ({ DeskUID, Day }) => [DeskUID, Day].join('|'),
offers = [{ DeskUID: "B11A13", Day: "2020-06-06" }, { DeskUID: "B11A13", Day: "2020-06-07" }, { DeskUID: "B12B34", Day: "2020-06-23" }],
reservations = [{ DeskUID: "B11A13", Day: "2020-06-06", Name: "Mike" }, { DeskUID: "B12B34", Day: "2020-06-23", Name: "Ali" }],
reservationsSet = new Set(reservations.map(getKey)),
open = offers.filter(o => !reservationsSet.has(getKey(o)));
console.log(open);
You can simply filter it with some inside it.
var offers = [{ DeskUID: "B11A13", Day: "2020-06-06" }, { DeskUID: "B11A13", Day: "2020-06-07" }, { DeskUID: "B12B34", Day: "2020-06-23" }];
var reservations = [{ DeskUID: "B11A13", Day: "2020-06-06", Name: "Mike" }, { DeskUID: "B12B34", Day: "2020-06-23", Name: "Ali" }];
var result = offers.filter(k=>!reservations.some(d=>d.DeskUID == k.DeskUID && d.Day==k.Day));
console.log(result);
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();
Let's say you have the following object as a string:
var timecard = {
"name": "Joe",
"time": "Sun Apr 26 2015 13:58:54 GMT-0400 (EDT)"
}
// as string
var stringed = 'var timecard = { "name": "Joe", "time": "Sun Apr 26 2015 13:58:54 GMT-0400 (EDT)" }'
and you run JSON.parse(stringed) to parse it into the object. How would you go about having it convert the date into an actual Date object as opposed to a string?
Thanks!
The JSON data format doesn't have a date type, so you have to write the code to transform it into a Date object yourself.
You can pass a reviver function as the second argument to JSON.parse to do that.
function parseDate(k, v) {
if (k === "time") {
return new Date(v);
}
return v;
}
var json = '{ "name": "Joe", "time": "Sun Apr 26 2015 13:58:54 GMT-0400 (EDT)" }';
var data = JSON.parse(json, parseDate);
console.log(data);