Creating Sorted Rows with JavaScript - javascript

At my wits end, I think I may be going code blind but can't for the life of me figure out what is causing the issue.
The desired outcome is for there to be only one date per row in the data array and as many flights for each date.
This works for the first item, but not any of the others, ending up with duplicate dates.
Where am I going wrong?
Desired data:
example in coming data 5 objects, only two dates.
["2020-02-20", "LGW"]
["2020-02-20", "LTN"]
["2020-02-20", "LHR"]
["2020-02-26", "LTN"]
["2020-02-26", "LHR"]
an array of two objects (one for each date), with the flights an array by date in the respective date object.
data = [ ["2020-02-20", ["LGW","LTN","LHR"]],
["2020-02-26", ["LTN","LHR"]]
]
Code shown below with comments:
function getRows(alternatives) {
var data = [];
for (var i = 0; alternatives.length > i; i++) {
var tmp = new Date(parseInt(alternatives[i].substring(0, 10)) * 1000);
var month = (tmp.getMonth() + 1);
var date = tmp.getFullYear() + "-" + (month < 10 ? "0" + month : month) + "-" + tmp.getDate();
var airport = alternatives[i].slice(11, 14);
var rowData = {
date: date,
flights: []
};
// if data has objects, check to see if the date is in any of the objects, if it isn't then add rowData to data
if (data.length > 0) {
for (var j = 0; data.length > j; j++) {
if (data[j].date === rowData.date) {
//if there are no flights, add the airport, if there are, is the airport already there, if not, add it
if (data[j].flights.length > 0 || !data[j].flights.includes(airport)) {
data[j].flights.push(airport);
}
}
else {
data.push(rowData);
continue;
}
}
}
else {
rowData.flights.push(airport);
data.push(rowData);
}
}
// not working, dupe dates are appearing in the rows
return data;
}

You can use reduce, create the object which has date as key with value consisting of array with date and array of flights. Check if key already exist, if present then only push in the flights array.
const input = [["2020-02-20", "LGW"],
["2020-02-20", "LTN"],
["2020-02-20", "LHR"],
["2020-02-26", "LTN"],
["2020-02-26", "LHR"]];
const output = Object.values(input.reduce((accu, [date, flight]) => {
if(!accu[date]) {
accu[date] = [date, [flight]];
} else {
accu[date][1].push(flight);
}
return accu;
}, {}));
console.log(output);

Related

Dynamic multidemension Array with Date keys in Javascript

how do I loop the newly created dynamic array by key and sub array.
var days = new Array();
$.each(json_object, function(r, row) {
var online_date = new Date(row.date_field * 1000);
var day_key = '' + online_date.getFullYear() + '' + (online_date.getMonth()+1) + '' + online_date.getDate() + '';
if(!days[day_key]) {
days[day_key] = [];
}
days[day_key][r] = row;
});
console.log('days.length');
console.log(Object.keys(days).length);
// 3 days woth of data..
// 20, 30 records each day...
for(var d = 0; d < Object.keys(days).length; d++) {
var day = days[d];
// day is undefined
console.log(day);
// I want KEY for 'day_key' and the data rows...
}
I'm using jQuery or basic JS.
If I filter or sort the array I loose my Keys, which I need as I want to graph out per day.
Thanks.
You should declare days as an object, not an array:
var days = {};
$.each(json_object, function(r, row) {
var online_date = new Date(row.date_field * 1000);
var day_key = '' + online_date.getFullYear() + '' + (online_date.getMonth()+1) + '' + online_date.getDate() + '';
if(!days[day_key]) {
days[day_key] = []; // Define an array for the rows to go into
}
days[day_key].push(row); // Add the row to the array
});
console.log('days.length');
console.log(Object.keys(days).length);
// 3 days worth of data..
// 20, 30 records each day...
Object.keys(days).forEach(day => {
console.log(day);
// I want KEY for 'day_key' and the data rows...
// The array of rows for the day are available
console.log(`Rows for ${day}: `,days[day])
})
I think this will do what you want

Google Script does not trigger as expected given row conditions

I have the 2 columns in my table schema:
Column D= Date, i.e. 20180611 [yyymmdd]
Column F= Continuous Value, i.e. 0.1, 0.6, -0.3 etc.
This is what I want to happen:
Check in column D for yesterday's date. Then, take in the corresponding row, and check if column F is greater than 0.5 (for yesterday's date). If TRUE, then send an email alert.
This is the script I have but it does not trigger for some reason. What is wrong with it?
function readCell() {
var sheet = SpreadsheetApp.getActive().getSheetByName('test');
var dates = sheet.getRange('D1:D').getValues();
var date = null;
var dateRow = 0;
var dateCount = dates.length;
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
var yesterdayString = yesterday.toDateString();
for (dateRow; dateRow < dateCount; ++dateCount) {
try {
date = dates[dateRow].toDateString();
if (date === yesterdayString) {
++dateRow;
// To account for zero-based array
break;
}
} catch (error) {
Logger.log(error);
}
}
var value = sheet.getRange('F' + dateRow).getValue();
if (value >= 0.5) {
var result = ('Alert found on: ' + date);
MailApp.sendEmail('blabla#gmail.com', 'Alert', result);
}
};
Here is the data
The problem could be due to the use of an open reference D2:D to get values and then use dates.length to set the number of iterations on the for loop because it could be a number too large.
One "quick and dirty" way that could solve the above issue is to replace
var dateCount = dates.length;
by
var dateCount = sheet.getDataRange().getValues().length;

Push to array with index method (JavaScript)

I am having difficulty pushing objects to an array of arrays via indices. Find below my current (awfully duplicative code) which reads through a CSV file's lines (Format: Date, reasonCode), and then creates FROM and TO (date) pairs depending on the reasonCode. This array is then used for Highcharts (Gantt chart). Please note the fromto1 and fromto2 arrays.
csv = csv.split(/\n/g);
var fromto1 = []; //array of FROM and TO pairs of code 1
fromto2 = []; //array of FROM and TO pairs of code 2
count = [];
lastFrom = [];
for (var i=1;i<3;i++) { //set all count and lastFrom variables to 0 //bs
count[i] = 0;
lastFrom[i] = 0;
}
jQuery.each(csv, function(i, line) {
line = line.split(','); //splits line, returns array of splitted values
date = parseInt(line[0], 10)*1000; //read date from line into string
reasonC = parseInt(line[2], 10); //read reasonC from line into string
if (reasonC == "1") {
count[1]++;
if (count[1] % 2 !=0){ //if it is an uneven value (FROM values)
lastFrom[1] = date; //temporary save the date in lastFrom[]
}
else { //if it is an even value (TO value), push the pair
fromto2.push({
from: lastFrom[1],
to: date
});
}
}
if (reasonC == "2") {
count[2]++;
if (count[2] % 2 !=0){
lastFrom[2] = date;
}
else {
fromto3.push({
from: lastFrom[2],
to: date
});
}
}
Why can't I replace the above code with this (Please note the fromto array of arrays):
csv = csv.split(/\n/g);
var fromto = [];
count = [];
lastFrom = [];
for (var i=1;i<3;i++) { //set all count and lastFrom variables to 0
count[i] = 0;
lastFrom[i] = 0;
fromto.push(new Array());
console.log(i+': New Array Pushed');
}
jQuery.each(csv, function(i, line) {
line = line.split(','); //splits line, returns array of splitted values
date = parseInt(line[0], 10)*1000; //read date from line into string
reasonC = parseInt(line[2], 10); //read reasonC from line into string
for (var c=1;c<3;c++) {
if (reasonC == c.toString()) {
count[c]++;
if (count[c] % 2 !=0){ //if it is an uneven value (FROM values)
lastFrom[c] = date; //temporary save the date in lastFrom[]
}
else { //if it is an even value (TO value), push the pair
fromto[c].push({
from: lastFrom[c],
to: date
});
}
}
}
}
I believe the problem is with fromto[c].push({ as it stays blank arrays.
I'm still a Jsnoob and couldn't find any answers on other threads, your help would be highly appreciated
There's quite a few things in your JavaScript that can do with some tips on how to do what you want to do using best practices, so an answer + advice.
1) multiple variables in a single declaration are separated by commas, not semi-colos:
var csv = csv.split(/\n/g),
fromto = [],
count = [],
lastFrom = [];
2) Don't use the Array object for making arrays.
fromto.push([]);
3) JS has function scoping only if you use var. Without var, variables are global.
jQuery.each(csv, function(i, line) {
line = line.split(',');
var date = parseInt(line[0], 10)*1000,
reasonC = parseInt(line[2], 10);
4) == is a coercing equality, and will see if there is any way two values can be considered the same. 4 == "4" is true, 4 === "4" is not.
if (reasonC == c) { ...
or
if (reasonC === c.toString()) { ...
5) JavaScript has forEach baked in, why would you use jQuery for something that's part of JavaScript already?
csv.forEach(function(line) {
...
});
And then the answer to your question, of course. It looks like you're trying to turn this data:
123,somevalue,1
456,somevalue,2
...
into this structure:
[
{ from: 123, to: 456 },
{ from: ..., to: ...},
...
]
You're relying on the line order to tell you which date is a from and which is a to; that's bound to go wrong, but you know your data best. (If I were writing this, I would operate on the assumption that line ordering is unknown)
var cvs = data.split(",");
parity = 0,
fields,
odd = [],
even = [],
fromTo = [];
cvs.forEach(function(line) {
parity = (parity + 1) % 2;
fields = line.split(",");
bin = parseInt(fields[2],10);
if(parity===1) {
odd[bin] = fields;
} else {
even[bin] = fields;
fromTo[bin].push({
from: odd[bin][0],
to: even[bin][0]
});
}
});
Now, this should work but this code is also really scary, because it still relies on line ordering in the CVS file, and without a hard guarantee that this is the case (like preprocessing validation), this (like your code) will do horrendously wrong things the moment two lines are accidentally in the wrong order.

How to sort just a single column in 2d array

I have a 2d array called dateTime[]. dateTime[count][0] contains future datetime and dateTime[count][1] contains a 4 digit value like 1234 or something.
I am trying to sort the column 0 that is dateTime[count][0] in ascending order. ( i,e, sorting the colunm 0 of the 2d array according to closest datetime from now)
Suppose my javascript 2d array is like:
dateTime[0][0] = 2/26/2013 11:41AM; dateTime[0][1] = 1234;
dateTime[1][0] = 2/26/2013 10:41PM; dateTime[1][1] = 4567;
dateTime[2][0] = 2/26/2013 8:41AM; dateTime[2][1] = 7891;
dateTime[3][0] = 3/26/2013 8:41AM; dateTime[3][1] = 2345;
I just wrote like this actually this is how I inserted value to dateTime[count][0] ; = new Date(x*1000); where x is unix time()
How I want the array to look after sorting:
dateTime[0][0] = 2/26/2013 8:41AM; dateTime[0][1] = 7891;
dateTime[1][0] = 2/26/2013 11:41AM; dateTime[1][0] = 1234;
dateTime[2][0] = 2/26/2013 10:41PM; dateTime[2][1] = 4567;
dateTime[3][0] = 3/26/2013 8:41AM; dateTime[3][1] = 2345;
please let me know how to solve this with less code.
Thanks. :)
This what I have done till now (I haven't sorted the array, also here dateTime is called timers)
function checkConfirm() {
var temp = timers[0][0];
var timeDiv = timers[0][1];
for (var i=0;i<timers.length;i++) {
if (timers[i][0] <= temp) { temp = timers[i][0]; timeDiv = timers[i][1]; }
}
if (timers.length > 0 ){ candidate(temp,timeDiv); }
}
function candidate(x,y) {
setInterval(function () {
var theDate = new Date(x*1000);
var now = new Date();
if ( (now.getFullYear() === theDate.getFullYear()) && (now.getMonth() === theDate.getMonth()) ) {
if ( (now.getDate() === theDate.getDate()) && (now.getHours() === theDate.getHours()) ) {
if ( now.getMinutes() === theDate.getMinutes() && (now.getSeconds() === theDate.getSeconds()) ) { alert("its time"); }
}
}
}, 10);
}
AT the end, I wanted to alert the user every time when the current time matches the time in the array. This is how I tried to solve the problem but this is completely wrong approach.
Use the .sort() function, and compare the dates.
// dateTime is the array we want to sort
dateTime.sort(function(a,b){
// each value in this array is an array
// the 0th position has what we want to sort on
// Date objects are represented as a timestamp when converted to numbers
return a[0] - b[0];
});
DEMO: http://jsfiddle.net/Ff3pd/

Count duplicate dates in list and occurance of duplicate dates in count

I am having list of dates in which i need to check for duplicates and occurances of duplicate dates in count i need to implement in javascript...
Try to help me out
thank in advance.
EX: { 12/11/2011, 12/11/2011, 11/4/2012, 12/6/2012, 12/6/2012, 12/6/2012}
Desire output: {12/11/2011, 11/4/2012, 12/6/2012}
count: 12/11/2011 =2
count: 12/6/2012 =3
Use Underscore.js
_.reduce(list, iterator, memo, [context]) Aliases: inject, foldl Also known as inject and foldl, reduce boils down a list of values into a
single value. Memo is the initial state of the reduction, and each
successive step of it should be returned by iterator.
Example:
var dates = [ '1/1/2006', '1/1/2006', '1/1/2007', '1/1/2007', '1/1/2007', '1/1/2006', '1/1/2012', '1/1/2006', '1/1/2009', '1/1/2012'];
var x = _.reduce(dates,
function(counts, date) {
counts[date] = (counts[date] || 0) + 1;
return counts;
}, {});
alert(JSON.stringify(x));
Produces
{"1/1/2006":4,"1/1/2007":3,"1/1/2012":2,"1/1/2009":1}
​
If your dates are strings (stored as a string) you can try something like this:
var dates = ["12/11/2011", "12/11/2011", "11/4/2012", "12/6/2012", "12/6/2012", "12/6/2012"];
var dates_set = {}; // key will be date, and values will be count
for (var i = dates.length - 1; i >= 0; i--) {
var d = dates[i];
if (dates_set.hasOwnProperty(d)) { // already is in our set, just increase counter
dates_set[d] = dates_set[d] + 1;;
} else { // there is no such date, lets add it
dates_set[d] = 1
}
};
document.write(dates_set["12/11/2011"]);
document.write("<br />");
document.write(dates_set["12/6/2012"]);

Categories

Resources