While working on custom calendar, I can't figure out how to find time slots that overlaps any other time slot.
Time slots start from 0 to 720 (9am to 9pm with each pixel representing a minute).
var events = [
{id : 1, start : 0, end : 40}, // an event from 9:00am to 9:40am
{id : 2, start : 30, end : 150}, // an event from 9:30am to 11:30am
{id : 3, start : 20, end : 180}, // an event from 9:20am to 12:00am
{id : 4, start : 200, end : 230}, // an event from 12:20pm to 12:30pm
{id : 5, start : 540, end : 600}, // an event from 6pm to 7pm
{id : 6, start : 560, end : 620} // an event from 6:20pm to 7:20pm
];
Each time slots is of one hour, for example 9 to 10, 10 to 11, 11 to 12 and so on.
In the above example, three events (id: 1,2,3) are overlapping for the 9-10 start time: 9:00, 9:30 and 9:20. And other events overlapping are int time slot of 6 to 7 (id: 5, 6) with 6 and 6:20 start times. The event with id 4 doesn't have any overlapping events in the time slot of 12 to 1.
I am looking for a way to get all overlapping event ids as well as number of events in a particular time slot, this is expected output:
[
{id:1, eventCount: 3},
{id:2, eventCount: 3},
{id:3, eventCount: 3},
{id:5, eventCount: 2},
{id:6, eventCount: 2}
]
For ids (1 to 3), there are 3 events for time slot 9 to 10 and 2 events for time slot 6 to 7.
I have created this formula to convert time number to actual time:
var start_time = new Date(0, 0, 0, Math.abs(events[i].start / 60) + 9, Math.abs(events[i].start % 60)).toLocaleTimeString(),
var end_time = new Date(0, 0, 0, Math.abs(events[i].end / 60) + 9, Math.abs(events[i].end % 60)).toLocaleTimeString();
This is what I have so far:
function getOverlaps(events) {
// sort events
events.sort(function(a,b){return a.start - b.start;});
for (var i = 0, l = events.length; i < l; i++) {
// cant figure out what should be next
}
}
DEMO if you need.
from my jquery-week-calendar commit, this is how i do it:
_groupOverlappingEventElements: function($weekDay) {
var $events = $weekDay.find('.wc-cal-event:visible');
var complexEvents = jQuery.map($events, function (element, index) {
var $event = $(element);
var position = $event.position();
var height = $event.height();
var calEvent = $event.data('calEvent');
var complexEvent = {
'event': $event,
'calEvent': calEvent,
'top': position.top,
'bottom': position.top + height
};
return complexEvent;
}).sort(function (a, b) {
var result = a.top - b.top;
if (result) {
return result;
}
return a.bottom - b.bottom;
});
var groups = new Array();
var currentGroup;
var lastBottom = -1;
jQuery.each(complexEvents, function (index, element) {
var complexEvent = element;
var $event = complexEvent.event;
var top = complexEvent.top;
var bottom = complexEvent.bottom;
if (!currentGroup || lastBottom < top) {
currentGroup = new Array();
groups.push(currentGroup);
}
currentGroup.push($event);
lastBottom = Math.max(lastBottom, bottom);
});
return groups;
}
there's a bit of component-specific noise around, but you'll get the logic:
sort the events by their starting ascending
sort the events by their ending ascending
iterate over the sorted events and check the starting/ending of the previous event (done rather by position, than by the event properties themself - just because the design might overlap, but the events not ... eg: making a border 2px, events with not overlapping start/end-times might overlap or "touch")
each overlapping-group (currentGroup) is a new array inside the groups-array
soo ... your code might look sth alike this (btw, no need to work with the real date-instances)
events.sort(function (a, b) {
var result = a.start - b.start;
if (result) {
return result;
}
return a.end - b.end;
});
var groups = new Array();
var currentGroup;
var lastEnd = -1;
jQuery.each(events, function (index, element) {
var event = element;
var start = event.start;
var end = event.end;
if (!currentGroup || lastEnd < start) {
currentGroup = new Array();
groups.push(currentGroup);
}
currentGroup.push(event);
lastEnd = Math.max(lastEnd, end);
});
return groups;
soo ... you are not willed to push some own energy into your problem ... well
var output = new Array();
jQuery.each(groups, function (index, element) {
var group = element;
if (group.length <= 1) {
return;
}
jQuery.each(group, function (index, element) {
var event = element;
var foo = {
'id': event.id,
'eventCount': group.length
};
output.push(foo);
});
});
To me it is easier to use timestamps for each start and end event, that way you can work with them directly or change them to date objects. To get the value, create a date object for each start and end, then:
var a.start = startDate.getTime();
var a.end = endDate.getTime();
For overlap:
if (a.start <= b.start && a.end > b.start ||
a.start < b.end && a.end >= b.end) {
// a overlaps b
}
You can leave them as date objects if you like, the above will work just as well.
Edit
Ok here's a working example:
Assuming a nominal date of 2012-05-15, then the events array looks like:
// Use iso8601 like datestring to make a local date object
function getDateObj(s) {
var bits = s.split(/[- :]/);
var date = new Date(bits[0], bits[1] - 1, bits[2]);
date.setHours(bits[3], bits[4], 0);
return date;
}
var events = [
{id: 1, start: getDateObj('2012-05-15 09:00'), end: getDateObj('2012-05-15 09:30')},
{id: 2, start: getDateObj('2012-05-15 09:30'), end: getDateObj('2012-05-15 11:30')},
{id: 3, start: getDateObj('2012-05-15 09:20'), end: getDateObj('2012-05-15 12:00')},
{id: 4, start: getDateObj('2012-05-15 12:20'), end: getDateObj('2012-05-15 12:30')},
{id: 5, start: getDateObj('2012-05-15 18:00'), end: getDateObj('2012-05-15 19:00')},
{id: 6, start: getDateObj('2012-05-15 18:20'), end: getDateObj('2012-05-15 19:20')}
];
function getOverlappingEvents(eventArray) {
var result = [];
var a, b;
// Sort the event array on start time
eventArray.sort(function(a, b) {
return a.start - b.start;
});
// Get overlapping events
for (var i=0, iLen=eventArray.length - 1; i<iLen; i++) {
a = eventArray[i];
b = eventArray[i + 1];
if ((a.start <= b.start && a.end > b.start) ||
(a.start < b.end && a.end >= b.end) ) {
result.push([a.id, b.id]);
}
}
return result;
}
// Run it
alert(getOverlappingEvents(events).join('\n')); // 1,3 2,3 5,6
Here's code that will do what you want. As others have mentioned you'd probably be better served by storing date objects, but that's a different issue.
function getOverlaps(events) {
// sort events
events.sort(function (a, b) {
return a.start - b.start;
});
var results = [];
for (var i = 0, l = events.length; i < l; i++) {
var oEvent = events[i];
var nOverlaps = 0;
for (var j = 0; j < l; j++) {
var oCompareEvent = events[j];
if (oCompareEvent.start <= oEvent.end && oCompareEvent.end > oEvent.start || oCompareEvent.end <= oEvent.start && oCompareEvent.start > oEvent.end) {
nOverlaps++;
}
}
if (nOverlaps > 1) {
results.push({
id: oEvent.id,
eventCount: nOverlaps,
toString: function () {
return "[id:" + this.id + ", events:" + this.eventCount + "]"
}
});
}
}
return results;
}
Related
I have an array of objects with timestamps as a property:
Sample Input:
const data = [
{
_id: "602102db3acc4515d4b2f687",
createdDt: "2021-02-08T09:22:35.000Z",
},
{
_id: "6021024da706a260d8932da2",
createdDt: "2021-02-08T09:20:13.000Z",
},
// ...
// ...
{
_id: "6020fd863acc4515d4b2f685",
createdDt: "2021-02-08T08:59:50.000Z",
},
];
Now starting from the current date, I need counts of total objects with timestamps of this day, previous day and so on (count can be zero if there is no entry in the previous day).
In the same way, I need counts for this day, previous day and so on, also same with weeks and months.
For example, the output I am expecting could be like:
Sample Output:
const result = {
days: [0, 0, 5, 10, ...],
weeks: [15, 5, 8, 0, ...],
months: [30, 42, 33, 23, ...]
}
I am using ES6, Lodash and moment.js. This is for basic graphical representation.
Update:
This is the code I wrote, can someone suggest a simpler solution?
My current solution:
for (var i = 0, k = 1; i < 365; i++, k++) {
let dt = moment().subtract(i, "days");
let td = moment().subtract(k, "days");
builddays.push(0);
for (var j = 0; j < drivers.length; j++) {
let ddt = new Date(drivers[j].createdDt);
if (moment(ddt).isBetween(td, dt)) builddays[i] = drivers[j].count;
}
}
var weeksbifurcate = builddays.reduce((resultArray, item, index) => {
const chunkIndex = Math.floor(index / 7);
if (!resultArray[chunkIndex]) {
resultArray[chunkIndex] = [];
}
resultArray[chunkIndex].push(item);
return resultArray;
}, []);
var monthsbifurcate = builddays.reduce((resultArray, item, index) => {
const chunkIndex = Math.floor(index / 30);
if (!resultArray[chunkIndex]) {
resultArray[chunkIndex] = [];
}
resultArray[chunkIndex].push(item);
return resultArray;
}, []);
for (i = 0; i < 12; i++) {
days.push(builddays[i]);
weeks.push(weeksbifurcate[i].reduce(getSum, 0));
months.push(monthsbifurcate[i].reduce(getSum, 0));
}
Use moment # diff to find indices, i.e. dayIndex, weekIndex, monthIndex and put or increment the right index in corresponding array in result object:
const solve = (data) => {
const result = {
days: [],
weeks: [],
months: [],
};
data.forEach((item) => {
const today = moment();
const createdDt = moment(item.createdDt);
const dayIndex = today.diff(createdDt, "days");
const weekIndex = today.diff(createdDt, "weeks");
const monthIndex = today.diff(createdDt, "months");
result.days[dayIndex] = (result.days[dayIndex] || 0) + 1;
result.weeks[weekIndex] = (result.weeks[weekIndex] || 0) + 1;
result.months[monthIndex] = (result.months[monthIndex] || 0) + 1;
});
return result;
};
const data = [
{createdDt: "2021-03-03T00:00:00.000Z",},
{createdDt: "2021-03-03T00:00:00.000Z",},
{createdDt: "2021-03-01T00:00:00.000Z",},
{createdDt: "2021-02-28T00:00:00.000Z",},
{createdDt: "2021-02-27T00:00:00.000Z",},
{createdDt: "2021-02-27T00:00:00.000Z",},
{createdDt: "2021-02-27T00:00:00.000Z",},
{createdDt: "2021-02-24T00:00:00.000Z",},
{createdDt: "2021-02-23T00:00:00.000Z",},
];
console.log(solve(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
There might be few undefined values in the result, but there is no need to set it to 0 as it can be considered as 0 wherever you are going to show/use it.
I need to retrieve the list of all attendees and all emails for each calendar event on my calendar but I want all data for each event to be in one row. Currently it is giving me multiple lines for each event.
Current Output in Google Sheets:
Desired output in Google Sheets:
Below is my code:
function testImportCal() {
var sh1 = SpreadsheetApp.openById('Mycal12345678').getSheetByName('Calendar Import').getRange('A:I');
sh1.clearContent();
var mycal = 'mycal#gmail.com';
var cal = CalendarApp.getCalendarById(mycal);
var events = cal.getEvents(new Date('November 10, 2020 00:00:00 PST'), new Date('December 20, 2020 00:00:00 PST'));
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Calendar Import');
var header = [['Event Title', 'Event Description', 'Attendees', 'Attendees Email', 'Created By', 'Event Start', 'Event End', 'Date Created', 'Last Updated']];
var range = sheet.getRange(1, 1, 1, 9);
range.setValues(header);
function getEmailsFromArray(guestsArray) {
var guestEmails = [];
for (var i = 0; i < guestsArray.length; i++) {
guestEmails.push(guestsArray[i].getEmail());
}
return guestEmails;
}
var row = 3;
for (var i = 0; i < events.length; i++) {
var myformula_placeholder = '';
Logger.log('Event ' + i + ': ' + events[i].getId());
var guestList = events[i].getGuestList(); //GET THE EMAIL AND STATUS OF EACH GUEST FOR EACH EVENT
for (var d = 0; guestList != null && d < guestList.length; d++) {
guestEmail = guestList[d].getEmail();
guestName = guestList[d].getName();
Logger.log('Guest ' + d + ': ' + guestList[d].getEmail());
var details = [[events[i].getTitle(), events[i].getDescription(), guestList[d].getName(), guestList[d].getEmail(), events[i].getCreators(), events[i].getStartTime(), events[i].getEndTime(), events[i].getDateCreated(), events[i].getLastUpdated()]];
var range = sheet.getRange(row, 1, 1, 9);
Logger.log(details);
var range2 = sheet.getRange(row - 1, 1, 1, 9);
range2.setValues(details);
row++; // increment row to start the next output after the previous output
}
}
}
You're getting it multiple times because you're using setValues() inside the loop that iterates over the guests, so you're adding the same event as many time as there are guests.
So you should probably move that setValues() to outside of the loop. In fact, you don't need to do an explicit loop if you use map():
function testImportCal() {
var sheet = SpreadsheetApp.openById('SHEET_ID').getSheetByName('Calendar Import');
sheet.clearContents();
var mycal = 'CALENDAR_ID';
var cal = CalendarApp.getCalendarById(mycal);
var events = cal.getEvents(new Date('November 10, 2020 00:00:00 PST'), new Date('December 20, 2020 00:00:00 PST'));
//var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Calendar Import');
var header = [['Event Title', 'Event Description', 'Attendees', 'Attendees Email', 'Created By', 'Event Start', 'Event End', 'Date Created', 'Last Updated']];
var range = sheet.getRange(1, 1, 1, 9);
range.setValues(header);
function getEmailsFromArray(guestsArray) {
var guestEmails = [];
for (var i = 0; i < guestsArray.length; i++) {
guestEmails.push(guestsArray[i].getEmail());
}
return guestEmails;
}
var row = 3;
for (var i = 0; i < events.length; i++) {
var myformula_placeholder = '';
//Logger.log('Event ' + i + ': ' + events[i].getId());
var guestList = events[i].getGuestList(); //GET THE EMAIL AND STATUS OF EACH GUEST FOR EACH EVENT
// for (var d = 0; guestList != null && d < guestList.length; d++) {
// guestEmail = guestList[d].getEmail();
// guestName = guestList[d].getName();
// Logger.log('Guest ' + d + ': ' + guestList[d].getEmail());
//
// var details = [[events[i].getTitle(), events[i].getDescription(), guestList[d].getName(), guestList[d].getEmail(), events[i].getCreators(), events[i].getStartTime(), events[i].getEndTime(), events[i].getDateCreated(), events[i].getLastUpdated()]];
// var range = sheet.getRange(row, 1, 1, 9);
// Logger.log(details);
//
// var range2 = sheet.getRange(row - 1, 1, 1, 9);
// range2.setValues(details);
// row++; // increment row to start the next output after the previous output
// }
var details = [[events[i].getTitle(), events[i].getDescription(), events[i].getGuestList().map(guest => guest.getName()), events[i].getGuestList().map(guest => guest.getEmail()), events[i].getCreators(), events[i].getStartTime(), events[i].getEndTime(), events[i].getDateCreated(), events[i].getLastUpdated()]];
var range = sheet.getRange(row, 1, 1, 9);
Logger.log(details);
var range2 = sheet.getRange(row - 1, 1, 1, 9);
range2.setValues(details);
row++; // increment row to start the next output after the previous output
}
}
As a side note, there's a lot of unnecessary code there, so you might want remove it to make it easier to understand. :)
Your main issue was that you were iterating over each guest and inserting the same event with each guest's information several times. To solve this you need to move your details and setValues() outside the guest loop and store the guests in an array. Then, you can simply convert this array into a string with the javascript method toString() and you will get a comma separated string of the array elements.
In the following piece of code I have explained in the comments the process I took with more details (modification points are after the comment indicating them):
Note: I have removed unnecessary lines of code you had that did not perform any specific function.
function testImportCal() {
var sh1 = SpreadsheetApp.openById('SHEETID').getSheetByName('SHEETNAME').getRange('A:I');
sh1.clearContent();
var mycal = 'CALENDARID';
var cal = CalendarApp.getCalendarById(mycal);
var events = cal.getEvents(new Date('November 10, 2020 00:00:00 PST'), new Date('December 20, 2020 00:00:00 PST'));
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('SHEETNAME');
var header = [['Event Title', 'Event Description', 'Attendees', 'Attendees Email', 'Created By', 'Event Start', 'Event End', 'Date Created', 'Last Updated']];
var range = sheet.getRange(1, 1, 1, 9);
range.setValues(header);
var row = 3;
//////////////////////// MODIFICATIONS ////////////////////////
for (var i = 0; i < events.length; i++) {
var guestList = events[i].getGuestList();
// Initialise guest detail arrays to store the information of all guests
var guestEmail=[];
var guestName=[];
//GET THE EMAIL AND STATUS OF EACH GUEST FOR EACH EVENT (no need to check if they are null with this array implementation)
for (var d = 0;d < guestList.length; d++) {
// Add the email and name to their corresponding arrays
guestEmail.push(guestList[d].getEmail());
guestName.push(guestList[d].getName());
}
// After the loop is done add the event details
// NOTE that for the guest lists we are converting our arrays into strings which will automatically separate each element with a comma
var details = [[events[i].getTitle(), events[i].getDescription(), guestName.toString(), guestEmail.toString(), events[i].getCreators(), events[i].getStartTime(), events[i].getEndTime(), events[i].getDateCreated(), events[i].getLastUpdated()]];
var range = sheet.getRange(row, 1, 1, 9);
var range2 = sheet.getRange(row - 1, 1, 1, 9);
range2.setValues(details);
row++; // increment row to start the next output after the previous output
}
}
I have this sample array of objects
mangoes:[
{ quantity:5},
{ quantity:8},
{ quantity:13},
{ quantity:4}
]
When I remove x mangoes, that x should be subtracted from the first element in the array, and if that x exceed the first element then it should reduce the remained quantity in the second item in the array...and so forth.
This is to say, I need the quantity to be reduced starting from the first one in the array down to the second if it exceed, to the third etc..
For example, If I buy 2 mangoes, It should minus 2 in the first array element and the resulting mangoes array should be
mangoes:[
{ quantity:3},
{ quantity:8},
{ quantity:13},
{ quantity:4}
]
On the other hand, If I would have bought 7 mangoes, it should reduce all 5 from first array element and then remove 2 mangoes from the second element...and hence the final array would be like this below
mangoes:[
{ quantity:0},
{ quantity:6},
{ quantity:13},
{ quantity:4}
]
By Using Javascript, how can I achieve this?
WHAT I HAVE TRIED
I have tried like this below, It works only for the first element(case) when the x is less, but for other case it doesn't work;
var x = 2
var done = false
mangoes.forEach(function (item,i) {
if(mangoes[i].quantity>=x && !done){
item.quantity = mangoes[i].quantity - x
done = true
}
})
const takeMangoes = (num, from) => from.map(x => {
const take = Math.min(x.quantity, num);
num -= take;
// Original way, keep all properties, don't mutate original
//return {...x, quantity: x.quantity - take};
// Pick from below:
// New way 1, mutate original in place
x.quantity = x.quantity - take;
return x;
// New way 2, limit to OWN properties
return Object.getOwnPropertyNames(x).reduce((a, c) => {
a[c] = x[c];
if (c === 'quantity') {
a[c] -= take;
}
return a;
}, {});
}).filter(x => x.quantity > 0);
console.log(takeMangoes(2, [
{quantity: 5},
{quantity: 8},
{quantity: 13},
{quantity: 4},
]));
console.log('------------------------');
console.log(takeMangoes(7, [
{quantity: 5},
{quantity: 8},
{quantity: 13},
{quantity: 4},
]));
You can take a closure inside map and generate the desired result.
var mangoes=[ { quantity:5},{ quantity:8},{ quantity:13},{ quantity:4}];
var toReduce = 5;
var result = mangoes.map((num=>({quantity})=>(r = Math.min(quantity,num),num=num-r,({quantity:quantity-r})))(toReduce));
console.log(result);
You can achieve that with forEach this way. But I wouldn't recommend it because even if a quantity is found to be greater than the value to be deducted, it will still loop through the whole item list as you can't break out of a forEach loop
var mangoes = [
{ quantity:0},
{ quantity:6},
{ quantity:13},
{ quantity:4}
];
var x = 2
var done = false
mangoes.forEach(function (item,i) {
if(item.quantity< x){
item.quantity = 0;
x = x- item.quantity;
}else{
item.quantity = item.quantity-x;
x=0;
}
});
console.log(mangoes)
However, I would recommend using for..of..loop so that you could conditionally break out of the loop, i.e if the quantity is found to be greater than the ones to be deducted, just deduct and break out of the loop. There's no need of further iteration.
var mangoes = [
{ quantity:5},
{ quantity:6},
{ quantity:13},
{ quantity:4}
];
var x = 1
var done = false
for(let i of mangoes){
if(i.quantity >= x){
i.quantity = i.quantity -x;
x = x - i.quantity;
break;
}else{
x = x - i.quantity;
i.quantity = 0;
}
}
console.log(mangoes)
let x = 8;
const newMangoes = mangoes.map((mango) => {
if (!x) return mango;
if (x <= mango.quantity) {
newMango = {quantity: mango.quantity - x};
x = 0;
return newMango;
} else {
x = x - mango.quantity;
return {quantity: 0};
}
});
var getMangoes = function(requested){
var remaining = requested;
var supplied = 0;
for(var i = 0; i < mangoes.length() && supplied < requested; i++){
if(mangoes[i].quantity >= remaining){
mangoes[i].quantity -= remaining;
supplied += remaining;
}
else {
remaining -= mangoes[i].quantity;
supplied += mangoes[i].quantity;
}
}
return(supplied);
};
var mangoesIWant = 13;
var mangoesIGot = getMangoes(mangoesIWant);
I have the following array :
for (let i of lastBal) {
var amtToDetect = received_amt;
console.log('amt to detect', amtToDetect);
var lpcForLoop = i.lpc;
var lic_fee_for_loop = i.lic_fee;
var daysDifference_for_loop = i.lpdays;
var onlineLPC_for_loop = i.onlinelpc;
var total_amt_for_loop = i.total_amt;
console.log('lic fee for loop', i.lic_fee);
if (amtToDetect >= lic_fee_for_loop) {
var remainAmtAfterLPC = Math.floor(amtToDetect - lpcForLoop);
var paidLPC = amtToDetect - remainAmtAfterLPC;
if (remainAmtAfterLPC > 0) {
if (remainAmtAfterLPC >= lic_fee_for_loop) {
var remainBalanceAfterLicFee = remainAmtAfterLPC - lic_fee_for_loop
var paidLicFee = remainAmtAfterLPC - remainBalanceAfterLicFee;
var total_amt_payment = Math.floor(paidLicFee + lpcForLoop);
//for balance entry
var bal_lic_fee = Math.floor(lic_fee_for_loop - paidLicFee);
var bal_LPC = Math.floor(lpcForLoop - lpcForLoop);
var bal_total_amt = Math.floor(bal_lic_fee + bal_LPC);
}
}
}
//console.log('demand in for loop',demandInsertData);
let difference = paymentDate - lic_fee_due_date;
var daysDifference = Math.floor(difference / 1000 / 60 / 60 / 24);
var onlineLPC = Math.floor(lic_fee * 0.18 * daysDifference / 365);
var currentLPC = Math.floor(onlineLPC + bal_LPC);
var total_amt = Math.floor(lic_fee + currentLPC);
console.log('in end for loop');
i.lpc = onlineLPC;
i.lic_fee = lic_fee - i.lic_fee;
console.log('in end for loop lic fee', i.lic_fee);
i.lpdays = daysDifference;
i.total_amt = total_amt;
received_amt = remainBalanceAfterLicFee;
console.log('in end for loop received_amt', received_amt);
}
In the above for loop, I want to replace some elements from lastBal array.
At the end of the for loop, I tried to replace some elements as follows :
i.lic_fee = lic_fee - i.lic_fee;
However, values are not being replaced during the next iteration. Instead, old values are being assigned.
How can I find the issue here?
Edit
After changing elements values I want to use them in same for loop.
Means after 1st iteration in for loop I want to change the values of element and use the updated values in next iteration.
Here at end of loop values are updated, but in second iteration old values form lastBal are assign.
Edit 2: Added lastBal
last bal [ RowDataPacket {
demand_id: 42,
user_id: 4,
lic_id: 4,
description: 'Balance',
demand_start_date: '2020-07-01',
demand_end_date: '2020-09-30',
demand_fin_year: '2020-2021',
lic_fee: 27000,
form_fee: 0,
lic_fee_due_date: '2020-06-30',
lrc: 0,
srtax: 0,
lpc: 1224,
total_amt: 28224,
outstanding_amt: 28224,
lpdays: 92,
onlinelpc: 1224,
flag: 0,
lic_fee_pay_id: 0,
demand_added_date: '2020-04-28 19:43:14',
payment_date: '0000-00-00 00:00:00' },
RowDataPacket {
demand_id: 44,
user_id: 4,
lic_id: 4,
description: 'Balance',
demand_start_date: '2020-10-01',
demand_end_date: '2020-12-31',
demand_fin_year: '2020-2021',
lic_fee: 54000,
form_fee: 0,
lic_fee_due_date: '2020-09-30',
lrc: 0,
srtax: 0,
lpc: 1224,
total_amt: 55224,
outstanding_amt: 55224,
lpdays: 0,
onlinelpc: 0,
flag: 0,
lic_fee_pay_id: 0,
demand_added_date: '2020-04-28 19:52:25',
payment_date: '0000-00-00 00:00:00' } ]
Above array is fetch from database.I want to updated 2nd RowDataPacket after 1st iteration in for loop.values to updated 2nd RowDataPacket are dynamic.
Well, I did try to reproduce with your code while putting some sample values in the fields wherever necessay and I do see the expected modifications. Hence, you need to clarify where exactly you're not seeing the changes that you're expecting.
var lastBal = [{ lpc: 1, lic_fee: 2, lpdays: 9, onlinelpc: 4, total_amt: 2 }, { lpc: 3, lic_fee: 4, lpdays: 2, onlinelpc: 5, total_amt: 1 }];
var editedValues = {};
for (let i of lastBal) {
if (!(Object.keys(editedValues).length === 0 && editedValues.constructor === Object)) {
i = {...i, ...editedValues} ;
}
var amtToDetect = 5;
console.log('amt to detect', amtToDetect);
var lpcForLoop = i.lpc;
var lic_fee_for_loop = i.lic_fee;
var daysDifference_for_loop = i.lpdays;
var onlineLPC_for_loop = i.onlinelpc;
var total_amt_for_loop = i.total_amt;
console.log('lic fee for loop', i.lic_fee);
if (amtToDetect >= lic_fee_for_loop) {
var remainAmtAfterLPC = Math.floor(amtToDetect - lpcForLoop);
var paidLPC = amtToDetect - remainAmtAfterLPC;
if (remainAmtAfterLPC > 0) {
if (remainAmtAfterLPC >= lic_fee_for_loop) {
var remainBalanceAfterLicFee = remainAmtAfterLPC - lic_fee_for_loop
var paidLicFee = remainAmtAfterLPC - remainBalanceAfterLicFee;
var total_amt_payment = Math.floor(paidLicFee + lpcForLoop);
//for balance entry
var bal_lic_fee = Math.floor(lic_fee_for_loop - paidLicFee);
var bal_LPC = Math.floor(lpcForLoop - lpcForLoop);
var bal_total_amt = Math.floor(bal_lic_fee + bal_LPC);
}
}
}
//console.log('demand in for loop',demandInsertData);
var daysDifference = 5000;
var onlineLPC = 2000;
var currentLPC = 1000;
var total_amt = 1500;
console.log('in end for loop');
i.lpc = onlineLPC;
i.lic_fee = 4000 - i.lic_fee;
console.log('in end for loop lic fee', i.lic_fee);
i.lpdays = daysDifference;
i.total_amt = 7000;
received_amt = 11000;
console.log('in end for loop received_amt', received_amt);
editedValues = {
pc: onlineLPC,
lic_fee: lic_fee - i.lic_fee,
lpdays: daysDifference,
total_amt: total_amt,
onlinelpc: onlineLPC,
received_amt: remainBalanceAfterLicFee
} // Whatever values you'd like to retain for the subsequent execution
}
console.log(lastBal);
EDIT
- Updated accordingly as you updated your requirements.
Because you are not accessing the array index/key, or in this case the object in javascript.
Take a look at the code below, I can't change "b to bb" assigning "bb" to the variable display the value in the for loop (key). In this case key='bb' will print the value but it will not change it.
var test = [];
test = ['a','b','c','d','e','f','g','h','i'];
for (let key of test){
if (key == 'b') { key = 'bb'}
console.log(key);
}
test[1] = 'cc';
for (let key of test){
console.log(key);
}
In order to change the value in the object/array you need to reference the index/key from the original array. test[1]='cc'; then the value will be changed.
Run the code commenting the test[1]='cc'; line, you will see that the value was not change in the initial loop, then run it uncommenting the line.
For the particular case below, it seems using the .find function is significantly faster than simply using the element's index. Why is this?
You could use a different approach by using a random number to find the object.
Index:
var i = Math.floor(Math.random() * 10),
o = array[i];
vs Find:
var i = Math.floor(Math.random() * 10),
o = array.find(o => o.id === i);
with shared data
var array = [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }, { id: 8 }, { id: 9 }];
Then you get from jsperf (with EDGE):
Index: 31,707,818 ±0. 92% fastest
Find: 5,001,388 ±1.51% 84% slower
Conclusion
Index access is faster then using Array#find.
Both samples took less than 0ms
var now = new Date();
var items = [{id: 0}, {id: 1}, {id: 2}, {id: 3}];
var item = items[2];
document.write((new Date().getTime() - now.getTime()) + 'ms');
var now = new Date();
var items = [{id: 0}, {id: 1}, {id: 2}, {id: 3}];
var item = items.find(e => e.id === 2);
document.write((new Date().getTime() - now.getTime()) + 'ms');
But with 100K array size the picture is different
var items = [];
for(var id = 0; id < 100000; id++) {
items.push({id: id});
}
var now = new Date();
var item = items[99999];
document.write((new Date().getTime() - now.getTime()) + 'ms');
var items = [];
for(var id = 0; id < 100000; id++) {
items.push({id: id});
}
var now = new Date();
var item = items.find(e => e.id === 99999);
document.write((new Date().getTime() - now.getTime()) + 'ms');
As you can see of course direct access by index is much faster because the find method should check many items before it finds the correct one. I.e. the topic starter assumption (that direct access by index is slower than find method) is obviously incorrect