csv to multi-dimensional array - javascript

I'm far from good at javascript. I'm cobbling together a page to analyze a csv file and created a page with results.
So I'm using papaparse.js for csv parsing and the stepFn to process each line, to eliminate records using various selection criteria.
I've also included moment.js to handle dates and times.
so there's 3 pieces of data I want to work with. (I'm simplifying).
[fundraising] team, amount, and date (which I'll store as a unix time integer).
I've been trying to see if outdata[teamname] exists, and if it does, update the amount. And if the amount >= goalamount, then populate date (if it's not already populated).
basically my web page allows them to define selection criteria, a goal, and to choose whether the challenge was [who gets their first]/sort on date, or [who got the most] sort on amount. [where total can actually be a count or
if the team isn't in the outdata array, add it, and place in it the total and a date (which of course I have to check for goal-reaching).
I've tried
var exists = typeof outdata[thisteamname];
if (exists == undefined)
{
outdata.push({ team: thisteamname, total: usevalue, adate: 0 });
}
else
{
var z = outdata[thisteamname]['total'];
//---->>> Cannot read property 'total' of undefined
outdata[thisteamname]['total'] += usevalue;
}
etc .. but i think I'm going about it all wrong. Suggestions? I will also need to sort the outdata array by eithe date or total, and loop through it for a top-ten style list at the end to write html.
all help appreciated, I know my javascript looks rather BASICy.

Related

How can I keep only 100 latest entries in CSV file per group

I have an application where I need to measure timestamp based parameter values from each device. The information is heavily structured and the reason I haven't looked into databases is because I have to get all the data for 100 x 1000 = 100k rows every few minutes. I want to delete the data corresponding to the oldest timestamp in each group. I am using Python for programming but even JavaScript would do. I could not find the limit parameter in the Python CSV official module. Help is super appreciated.
Item 1
Timestamp, parameter1, parameter2...parameterN
...
100 rows
Item 2
Timestamp, parameter1, parameter2...parameterN
...
100 rows
...1000 items
Note: There are no headers to separate any rows, the Item 1,2 etc. are shown for representational purposes.
I need to be able to add new row every few minutes under each group and get rid of the old one effectively keeping the numbers at 100 per group
There's no limit parameter, because a reader is just an iterator, and Python has generic ways to do anything you might want to do with any iterator.
with open(path) as f:
r = csv.reader(f)
First 100:
itertools.islice(r, 100)
Last 100:
collections.deque(r, maxlen=100)
Max 100 by 3rd column:
heapq.nlargest(100, r, key=operator.itemgetter(2))
… and so on.
Store your data internally like this
dict [key] [timestamp][array of values]
data={}
if 'bob' in data:
data['bob']={}
data['bob'][timestamp]=list(values)
else:
data['bob'][new_timestamp]=list(values)
After 2 iterations your data array will look like
data['bob'][15000021][1,2,3,4,5]
data['bob'][15003621][5,6,7,8,9,0]
If you want the latest ... just get the unique keys for bob - and delete
- either anything more than n items (bob's values sorted by timestamp)
- or if the timestamp is less than now() - 2 days [or whatever your rule]
I use both mechanisms in similar datasets. I strongly suggest you then save this data, in case your process exists.
Should your data contain an OrderedDictionary (which would make the removal easier) - please not pickle will fail, however the excellent module dill (I am not kidding) is excellent, and handles all datatypes and closes much nicer IMHO.
** Moving from Comments **
I'm assuming reading the file from the bottom up help you... This can be done by prepending entries to the beginning of the file.
With that assumption you just need to rewrite the file on each entry. Read the new file to an array, push() the new entry, shift() the list and write to new file.
Alternatively you can continue to push() to the file and only read the first 100 entries. After doing your read you can remove the file and start a new one if you expect to consistently get more than 100 entries between reads, or you can clean the file to just 100 entries

How to add to the number value of an object property in Javascript / Angular5

I am building an app that records my spending with Angular 5. I want to take the data input which includes an integer(spend amount) and a date and basically show a daily spend amount as well as total spend and other weekly categories etc. The first thing I have been trying to get is a daily spend. So I thought it would be best to add dynamically to an object containing with property as date and value as total spend amount for that day. Adding dynamically to the object if the date in question doesn't exist yet. The part which currently doesn't work is that I can't seem to add to the value of an already defined property (e.g a date)
dailySpends =
{
"2017-12-01": 0, // <-- I want to add to this with every new entry that is also on this date for a running total.
}
I have a function which works on click called addItem(), it does a number of things and one of the things I want it to do is add to this running daily total. So far I have written this.
for(var key in this.dailySpends){
if(this.dailySpends[key] == this.date){
this.dailySpends[key] += this.spendAmount; //<<--Problematic line
alert(Object.entries(this.dailySpends)); //alert for checking entry
}
else this.dailySpends[this.date] = this.spendAmount;
alert(Object.entries(this.dailySpends)) //alert for checking entry
}
So update the object fine when new dates are put in, but I cant seem to update the value of already defined properties. Would it be better if I was working with an array, or is there a simple way of adding to it that I am missing.

Find the file having lowest timestamp

I have a requirement which needs to be done by only using Java Script and would appreciate if someone can help here.
We have 10 files coming into a folder of format MMddyyyyHHmmss (ex. 07192013114030) - MonthDayYearHourMinuteSecond
The file gets dropped from an external system once every day
When the 11th file comes in I need to find the file that was dropped on the first and delete it so that the total count of the files should always be 10 (latest 10 files)
Sample example
07192013114030
07202013114030
07212013114030
07222013114030
07232013114030
07242013114030
07252013114030
07262013114030
07272013114030
07282013114030
When the 11th file comes in on 07292013114030, I want to find the file 07192013114030 using Java Script.
I can provide the incoming file names in any format, ex. MM/dd/yyyy/HHmmss or MM_dd_yyyy_HH_mm_ss if that helps to do this using JS
Since you can get the dates in any format, get them in YYYYMMDDHHmmss format. Then get those timestamps in an array. There's not enough information about your system in your question to explain how to do this but just loop through the files pulling out the timestamps and pushing them into an array.
Basically you should have an array like this when you're done:
dates = ['20130719114030',
'20130720114030',
'20130721114030',
'20130722114030',
'20130723114030',
'20130724114030',
'20130725114030',
'20130726114030',
'20130727114030',
'20130728114030'];
Once done, simply sort the array:
dates.sort();
Dates will be in alphanumeric order, which also happens to be chronological order because of our date format. The oldest date will be the first one in the array, so
dates[0] // '20130719114030'
Again, there's not enough information about your system to explain how to delete the file, but perhaps you could loop through the files again to find a matching timestamp, then delete the file.
I'm not experienced with Javascript, but my logical progression would be:
Out of the 11 files, find the lowest year
If the same
Out of the 11 files, find the lowest month
[...]
all the way down to second
Convert them all to date objects and then compare them. You would only have to do two pass throughs of the list to find the smallest date (one to convert and one to compare)... instead of extracting each snippet and going through the list multiple times.
http://www.w3schools.com/js/js_obj_date.asp

Get next closest time from a table based on selected hours and minutes

I have a long table with columns of schedule data that I'm loading via a form with jQuery load(). I have access to these html pages with the table data and can add classes/data attributes etc.
My form has select fields for hours and minutes (defaulting to the current time) and I'm trying to get the next closest time plus the four after that.
The time data in my tables are all formatted as <td>H:MM</td>.
Ideally with jQuery, I was wondering how I can strip the table data of everything but those times. Alternatively, since I can reformat this data would I be making my life easier to format it a certain way?
Things I've tried - I am admittedly a novice at js so these things may seem silly:
Reading the first character of each cell and comparing it to the
selected hour. This is obviously a problem with 10, 11, 12 and is
really intensive (this is a mobile site)
Using a single time select field thenCreating an Array of each
column to compare with the selected time. Couldn't get this working
and also creates an issue with having to use a single select for
every time.
Basically looking for a little guidance on how to get this working short of, or maybe including, copying all the html tables into JSON format...
May as well post http://jsbin.com/ozebos/16/edit, though I was beaten to it :)
Basic mode of operation is similar to #nrabinowitz
On load, parse the time strings in some way and add to data on each row
On filter (i.e. user manipulates a form), the chosen time is parsed in the same way. The rows are filtered on row.data('time') >= chosen_time
The resulting array of elements limited to 5 (closest time plus four as OP requested) using .slice(0, 5)
All rows are hidden, these rows are displayed.
Some assumptions have been made, so this code serves only as a pointer to a solution.
I thought this was an interesting question, so I put together a jsFiddle here: http://jsfiddle.net/nrabinowitz/T4ng8/
The basic steps here are:
Parse the time data ahead of time and store using .data(). To facilitate comparison, I'm suggesting storing the time data as a float, using parseFloat(hh + '.' + mm).
In your change handler, use a loop to go through the cells in sequence, stopping when you find the index of the cell with a time value higher than your selected time. Decrement the index, since you've gone one step too far
Use .toggle(i >= index && i < index+4) in an .each() loop to hide and show the appropriate rows.
Here's how to do it on client side. This is just an outline, but should give you an idea.
// Create a sorted array of times from the table
var times = []
$('#mytable td').each(function(cell) {
times.push(cell.innerHTML);
});
times.sort();
// Those times are strings, and they can be compared, e.g. '16.30' > '12.30' returns true.
var currentTime = '12:30' // you probably need to read this from your select
var i = 0;
while (times[i] < currentTime || i=times.length) {
i++;
}
var closestTime = times[i];
var closestTimes = times.slice(i, i+4);
If you want to access not the times, but actually the cells containing the times, you can find them like this:
$('#mytable td').each(function() {
if ($(this).text() in closestTimes) {
// do something to that cell
}
})

javascript: array of object for simple localization

I need to implement a simple way to handle localization about weekdays' names, and I came up with the following structure:
var weekdaysLegend=new Array(
{'it-it':'Lunedì', 'en-us':'Monday'},
{'it-it':'Martedì', 'en-us':'Tuesday'},
{'it-it':'Mercoledì', 'en-us':'Wednesday'},
{'it-it':'Giovedì', 'en-us':'Thursday'},
{'it-it':'Venerdì', 'en-us':'Friday'},
{'it-it':'Sabato', 'en-us':'Saturday'},
{'it-it':'Domenica', 'en-us':'Sunday'}
);
I know I could implement something like an associative array (given the fact that I know that javascript does not provide associative arrays but objects with similar structure), but i need to iterate through the array using numeric indexes instead of labels.
So, I would like to handle this in a for cycle with particular values (like j-1 or indexes like that).
Is my structure correct? Provided a variable "lang" as one of the value between "it-it" or "en-us", I tried to print weekdaysLegend[j-1][lang] (or weekdaysLegend[j-1].lang, I think I tried everything!) but the results is [object Object]. Obviously I'm missing something..
Any idea?
The structure looks fine. You should be able to access values by:
weekdaysLegend[0]["en-us"]; // returns Monday
Of course this will also work for values in variables such as:
weekdaysLegend[i][lang];
for (var i = 0; i < weekdaysLegend.length; i++) {
alert(weekdaysLegend[i]["en-us"]);
}
This will alert the days of the week.
Sounds like you're doing everything correctly and the structure works for me as well.
Just a small note (I see the answer is already marked) as I am currently designing on a large application where I want to put locals into a javascript array.
Assumption: 1000 words x4 languages generates 'xx-xx' + the word itself...
Thats 1000 rows pr. language + the same 7 chars used for language alone = wasted bandwitdh...
the client/browser will have to PARSE THEM ALL before it can do any lookup in the arrays at all.
here is my approach:
Why not generate the javascript for one language at a time, if the user selects another language, just respond(send) the right javascript to the browser to include?
Either store a separate javascript with large array for each language OR use the language as parametre to the server-side script aka:
If the language file changes a lot or you need to minimize it per user/module, then its quite archivable with this approach as you can just add an extra parametre for "which part/module" to generate or a timestamp so the cache of the javascript file will work until changes occures.
if the dynamic approach is too performance heavy for the webserver, then publish/generate the files everytime there is a change/added a new locale - all you'll need is the "language linker" check in the top of the page, to check which language file to server the browser.
Conclusion
This approach will remove the overhead of a LOT of repeating "language" ID's if the locales list grows large.
You have to access an index from the array, and then a value by specifying a key from the object.
This works just fine for me: http://jsfiddle.net/98Sda/.
var day = 2;
var lang = 'en-us';
var weekdaysLegend = [
{'it-it':'Lunedì', 'en-us':'Monday'},
{'it-it':'Martedì', 'en-us':'Tuesday'},
{'it-it':'Mercoledì', 'en-us':'Wednesday'},
{'it-it':'Giovedì', 'en-us':'Thursday'},
{'it-it':'Venerdì', 'en-us':'Friday'},
{'it-it':'Sabato', 'en-us':'Saturday'},
{'it-it':'Domenica', 'en-us':'Sunday'}
];
alert(weekdaysLegend[day][lang]);

Categories