Im trying accept user input and then if it matches the first value in a row of my csv push that entire row to an array.
I have a csv that looks like this.
City,Lat,Lon,Date
Seattle,47.6,122.3,2015 06 03
Spokane, 47.65, 117.42,2015 06 04
I accept user input like this.
var city = window.prompt("Which city are looking for",);
console.log(city);
Then if the city the user entered matches a city in the csv I want to push it to a new array. Here is the code I wrote for it, but its not quite working.
d3.csv("./some.csv", function(data) {
var lst = [];
for (var i = 0; i < data.length; i++){
if (data.City[i] == 'city') {
lst.push(data[i]);
}
console.log(lst);
}
});
My desired output would look something like this.
[['Seattle',47.6,122.3,2015 06 03],
['Seattle',47.6,122.3,2015 06 05]]
Any suggestions would be greatly appreciated.
I can see several problems.
if (data.City[i] == 'city') {
data is an array, each entry of which is an object with properties with the same names as the column heads. So, instead of data.City[i] you want data[i].City.
Also you are comparing the result with the string literal 'city' instead of the variable city.
Finally you should probably use === to avoid confusing results.
So this line should probably read:
if (data[i].City === city) {
The other thing is the data structure returned by D3 does not match what you are expecting. Instead of:
[['Seattle',47.6,122.3,2015 06 03]]
you will get
[ { City: 'Seattle', Lat: 47.6, Lon: 122.3, Date: '2015 06 03' } ]
If that is a problem for you, you could consider using the d3.csv.parseRows method which returns the data in the form you are expecting. In that case you will need to adapt the comparison line accordingly.
Related
This script works brilliantly to pull emails into my sheet. My problem is that the function only pulls the first two fields listed. e.g., getPlainBody, getSubject - even though more fields are asked for. So instead of having one function that pulls all the fields I need (getPlainBody, getSubject, getTo, getDate, getFrom) I only get the first two (getPlainBody, getSubject). Is there an obvious modification that will pull all 5 fields into the sheet?
function getEmails_(q) {
sh0.clear();
var emails = [];
var threads = GmailApp.search(q);
for (var i in threads) {
var msgs = threads[i].getMessages();
for (var j in msgs) {
emails.push([msgs[j].getPlainBody(), [msgs[j].getSubject(), [msgs[j].getDate(), [msgs[j].getTo(), [msgs[j].getFrom()
]]]]]);
}
}
return emails;
}
function appendData_(sh0, array2d) {
sh0.getRange(sh0.getLastRow() + 1, 1, array2d.length, array2d[0].length).setValues(array2d);
}
function saveEmails() {
var array2d = getEmails_(SEARCH_QUERY);
if (array2d) {
appendData_(sh0, array2d);
}}
Your code is fine the problem is how you are constructing the 2D array.
in the .push() method, your use of the square brackets - [] - is building an array within an array within another array within another array within another array within another array, it's easier to see it in the screenshot below.
What you need is 1 array of horizontals cells with an array of vertical rows.
So change:
emails.push([msgs[j].getPlainBody(), [msgs[j].getSubject(), [msgs[j].getDate(), [msgs[j].getTo(), [msgs[j].getFrom()]]]]]);
to
emails.push([msgs[j].getPlainBody(), msgs[j].getSubject(), msgs[j].getDate(), msgs[j].getTo(), msgs[j].getFrom()]);
On a personal note, I usually always format the date to something a little more readable. You can use Utilities to do this. Ex: format: Thu Jun 15 2017 11:18:18 GMT+0700 (ICT) to 15/06/2017 # 11:18
var formatDate = Utilities.formatDate(emails[i][2], 'GMT+07:00', 'dd/MM/yyyy # HH:mm')
I have a series of documents each containing a date and a list of letters. I need the output to be a single, unique letter per key with the latest date for each letter as a value.
With a simple mapping function that looks like:
{
"_id": "_design/output",
"_rev": "1-c7b904b0e93709113c49127efb40187a",
"language": "javascript",
"views": {
"output": {
"map": "function(doc) {\n emit(doc.args.report.updated_partitions, doc.timestamp);\n}",
"reduce": "function(key, value, reduce) {\n return (value)\n}"
}
}
}
I get the following result:
{"total_rows":2,"offset":0,"rows":[
{"id":"8e561dd15fd33acfc7c4502c58008c2a","key":["a","b"],"value":1403818824},
{"id":"8e561dd15fd33acfc7c4502c5800a212","key":["a","c","d"],"value":1403818700}
]}
The output I'm looking for should look like:
{"total_rows":2,"offset":0,"rows":[
{"id":"8e561dd15fd33acfc7c4502c58008c2a","key":["a"],"value":1403818824},
{"id":"8e561dd15fd33acfc7c4502c58008c2a","key":["b"],"value":1403818824},
{"id":"8e561dd15fd33acfc7c4502c58008c2a","key":["c"],"value":1403818824},
{"id":"8e561dd15fd33acfc7c4502c5800a212","key":["d"],"value":1403818700}
]}
I actually found a simpler method. The basic steps are:
Map each individual letter to the date
Reduce the result by returning the maximum value from an array of all dates by key.
The map looks like:
function(doc) {
var files = doc.args.report.updated_partitions;
var timestamp = doc.timestamp;
for (i=0; i<files.length; i+= 1){
var file_name = files[i];
emit(file_name, timestamp);
}
}
And the reduce looks like:
function(key, value, reduce) {
return (Math.max.apply(null, value))
}
The result will be a unique key for each letter with the latest date from all docs as a value.
The use case for this is when each couch document has a list of files that were modified and the date the modification took place, but you would like to know the latest modification date for each individual document.
Here I load a JSON into a variable. But I am unable to find the length of the nested JSON.
var JVarible = [{"key":{"kind":"Comment","id":5992578889547776},"categoryId":0,"userName":"Shana Deepak","userId":"cpshana","comment":"hi.fghfghfgh ","createDate":"Sep 16, 2013 7:07:36 AM","url":"https://graph.facebook.com/100000840303512/picture?type\u003dsmall","networkType":"facebook","status":1,"nestmsgs":{"value":"[{\"key\":{\"kind\":\"Nestmsg\",\"id\":5914238686068736},\"commentId\":5992578889547776,\"userName\":\"Shana Deepak\",\"userId\":\"cpshana\",\"message\":\"dfgdfgfdg\",\"createDate\":\"Sep 16, 2013 7:22:01 AM\",\"url\":\"https://graph.facebook.com/100000840303512/picture?type\\u003dsmall\",\"networkType\":\"facebook\",\"status\":0},{\"key\":{\"kind\":\"Nestmsg\",\"id\":5281469744283648},\"commentId\":5992578889547776,\"userName\":\"Shana Deepak\",\"userId\":\"cpshana\",\"message\":\"gfdgdfgfd\",\"createDate\":\"Sep 16, 2013 7:12:25 AM\",\"url\":\"https://graph.facebook.com/100000840303512/picture?type\\u003dsmall\",\"networkType\":\"facebook\",\"status\":0}]"}}];
var i=0;
for (i=0; i<JVarible.length;i++)
{
alert(JVarible[i].['nestmsgs'].length)
}
First of all, JVarible does not contain JSON. It contains a JavaScript array. But one of the values inside that array is indeed JSON (contained in a string).
Your question is not very clear, but it seems you want to get the number of messages within each object. nestmsgs is actually an object with one property, value. value has a string containing JSON as value.
You first have to parse the JSON, which results in an array, and then you can determine its length:
for (var i = 0; i < JVarible.length; i++) {
var msgobj = JVarible[i].nestmsgs;
msgobj.value = JSON.parse(msgobj.value);
alert(msgobj.value.length)
}
Something like this?
Object.keys(JVarible[0]) //returns ["key", "categoryId", "userName", "userId", "comment", "createDate", "url", "networkType", "status", "nestmsgs"]
Object.keys(JVarible[0]).length //returns 10
I have an array of data get from the server(ordered by date):
[ {date:"2012-8", name:"Tokyo"}, {date:"2012-3", name:"Beijing"}, {date:"2011-10", name:"New York"} ]
I'd like to :
get the name of the first element whose date is in a given year, for example, given 2012, I need Tokyo
get the year of a given name
change the date of a name
which data structure should I use to make this effective ?
because the array could be large, I prefer not to loop the array to find something
Since it appears that the data is probably already sorted by descending date you could use a binary search on that data to avoid performing a full linear scan.
To handle the unstated requirement that changing the date will then change the ordering, you would need to perform two searches, which as above could be binary searches. Having found the current index, and the index where it's supposed to be, you can use two calls to Array.splice() to move the element from one place in the array to another.
To handle searches by name, and assuming that each name is unique, you should create a secondary structure that maps from names to elements:
var map = {};
for (var i = 0, n = array.length; i < n; ++i) {
var name = array[i].name;
map[name] = array[i];
}
You can then use the map array to directly address requirements 2 and 3.
Because the map elements are actually just references to the array elements, changes to those elements will happen in both.
Assuming you are using unique cities, I would use the city names as a map key:
cities = {
Tokyo: {
date: "2012-8"
},
New York: {
date: "2011-10"
}
}
To search by date:
function byDate(date) {
for(el in cities) {
if(cities.hasOwnProperty(el) && cities[el].date === date)
return el;
}
}
Just for the record: without redesigning your date structure you could use sorting combined with the Array filter or map method:
function sortByDate(a,b){
return Number(a.date.replace(/[^\d]+/g,'')) >
Number(b.date.replace(/[^\d]+/g,''));
}
var example = [ {date:"2012-8", name:"Tokyo"},
{date:"2012-3", name:"Beijing"},
{date:"2011-10", name:"New York"} ]
.sort(sortByDate);
//first city with year 2012 (and the lowest month of that year)
var b = example.filter(function(a){return +(a.date.substr(0,4)) === 2012})[0];
b.name; //=> Beijing
//year of a given city
var city = 'Tokyo';
var c = example.filter(function(a){return a.city === city;})[0];
c.year; //=> 2012
//change year of 'New York', and resort data
var city = 'New York', date = '2010-10';
example = example.map(
function(a){if (a.name === city) {a.date = date;} return a;}
).sort(sortByDate);
[
{"task":"test","created":"/Date(1291676980607)/"},
{"task":"One More Big Test","created":"/Date(1291677246057)/"},
{"task":"New Task","created":"/Date(1291747764564)/"}
]
I looked on here, and someone had the same sort of question, but the "checked" correct answer was that it will be different on IE if the item is deleted, which would be fine. My issue is, those items above are stored, but when i go and grab them, iterate, and return, the items are reversed and the created is at the 0 index and task is at 1. Also, i need to return this as JSON.
Here is my basic JS (value == an int the user is passing in):
outputJSON = {};
for(x in json[value]){
outputJSON[x] = _objectRevival(json[value][x]);
}
return outputJSON;
That returns:
created: Mon Dec 06 2010 15:09:40 GMT-0800 (Pacific Standard Time)
task: "test"
The order of the properties of an object is undefined. It is not possible to force them in a specified order. If you need them in a specific order, you can build this structure reliably using arrays:
var values = [
[["task", "test"], ["created", "/Date(1291676980607)/"]],
[["task", "One More Big Test"], ["created", "/Date(1291677246057)/"]],
[["task", "New Task"], ["created", "/Date(1291747764564)/"]]
];
Then you can iterate over your structure like this:
for (var i = 0; i < values.length; i++) {
for (var k = 0; k < values[i]; k++) {
// values[i][k][0] contains the label (index 0)
// values[i][k][1] contains the value (index 1)
}
}
To enforce a particular order for your output just replace json[value] in your for loop with an array of the object properties in the order you want to display them, in your case ["task", "created"].
The problem is that javascript objects don't store their properties in a specific order. Arrays on the other do (hence why you can get something consistent from json[0], json[1], json[2]).
If your objects will always have "task" and "created", then you can get at them in any order you want.
json[value]["task"]
and
json[value]["created"]
Update:
This should work with your existing code.
Before sending the json object:
var before = [
{"task":"test","created":"/Date(1291676980607)/"},
{"task":"One More Big Test","created":"/Date(1291677246057)/"},
{"task":"New Task","created":"/Date(1291747764564)/"}
];
var order = [];
for (var name in before[0]) {
order.push(name); // puts "task", then "created" into order (for this example)
}
Then send your json off to the server. Later when you get the data back from the server:
var outputJSON = {};
for (var x in order) {
if (order.hasOwnProperty(x)) {
outputJSON[order[x]] = _objectRevival(json[value][order[x]]); // I'm not sure what _objectRevival is...do you need it?
}
}
return outputJSON;
var items = ["bag", "book", "pen", "car"];
items.reverse();
This will result in the following output:
car , pen, book, bag
Even if you have JSON array it will reverse.