How to compare a variable against another from an array of objects? - javascript

I'm trying to compare event.feature.getProperty('township') against timeline.townshipname from my timeline array in my if. Checking for one right now with [0] is fine, but I have a whole column I want to check against. What's the best way to do this?
//Load Timelines
var timeline = [];
jQuery.getJSON(timelines, function(data) {
var entry = data.feed.entry;
jQuery(entry).each(function(){
var townshipname = this.gsx$township.$t;
var timelinename = this.gsx$timeline.$t;
var combined = {townshipname, timelinename};
timeline.push(combined);
});
});
// Output from timeline looks like
// 0: {townshipname: "West Quincy", timelinename: "Ready for drops"}
// 1: {townshipname: "Woodgate", timelinename: "Ready"}
//Add infowindow to identify townships
township_layer.addListener('click', function(event) {
if (event.feature.getProperty('township') == timeline[0].townshipname){
var timepush = timeline[0].timelinename
} else {
var timepush = 'No Timeline Entered'
}

You can create an array of township names from the timeline array of objects, so that you can compare if a specific township is found in your timeline.
This can be done by:
Using Array.prototype.map() to iterate through your timeline array of objects and return a list of all townshipname
Check if a given township is present in your array by using Array.prototype.indexOf()
Example code is as follow:
// Generate an array of townships extract from timeline
var townships = timeline.map(function(item) {
return item.townshipname;
});
// Attempt to search a given township in your generated array
var townshipIndex = townships.indexOf(event.feature.getProperty('township'));
if (townshipIndex !== -1) {
var timepush = timeline[townshipIndex].timelinename;
} else {
var timepush = 'No Timeline Entered';
}
Alternatively, you can use a for...of loop and break out of it once a match is found. We assume that no timeline is entered as the "ground state", and then we can update that once a match is found:
var timepush = 'No Timeline Entered';
for (var item of timeline) {
if (item.townshipname === event.feature.getProperty('township')) {
timepush = item.timelinename;
break;
}
}
If you really need IE support, then we can use the classic for loop:
var timepush = 'No Timeline Entered';
for (var i = 0; i < timeline.length; i++) {
if (timeline[i].townshipname === event.feature.getProperty('township')) {
timepush = timeline[i].timelinename;
break;
}
}

So there are a couple of different ways you could this, if you have an indexed array of objects the fastest way would be:
for(var i = 0; i < timeline.length; i++){
if(event.feature.getProperty('township') == timeline[i].townshipname){
var timepush = timeline[i].timelinename;
}
}
I can come up with another example shortly.

Related

Checking for an item in an array

I'm having trouble finding the right way to find if an item from a for loop is in an array. Let's say I have a for loop that is iterating through some results. If they are in an array:
ctids = [];
continue to the next step in the for loop, but if not, push them to the array and do something else. What is the correct syntax for this?
for (var i=0;i<results.features.length;i++){
ACS_BG = results.features[i].attributes.BLKGRPCE;
ACS_ST = results.features[i].attributes.STATEFP;
ACS_CNTY = results.features[i].attributes.COUNTYFP;
ACS_TRCT = results.features[i].attributes.TRACTCE;
if ACS_TRCT exists in ctids { //This is where I am having trouble.
continue; //skip the rest of the if statement
} else {
ctids.push(ACS_TRCT);
// do something else;
};
};
Can you please try this code
var ctids = []
for (var i=0;i<results.features.length;i++){
ACS_BG = results.features[i].attributes.BLKGRPCE;
ACS_ST = results.features[i].attributes.STATEFP;
ACS_CNTY = results.features[i].attributes.COUNTYFP;
ACS_TRCT = results.features[i].attributes.TRACTCE;
if(!ctids.includes(ACS_TRCT))
{
ctids.push(ACS_TRCT);
}
};
You can use includes to check if the elment exist in array and if not push the element into it.
if (ctids.includes(ACS_TRCT)){
continue;
}else{
ctids.push(ACS_TRCT)
}
I'd do:
for (var i = 0; i < results.features.length; i++) {
const ACS_BG = results.features[i].attributes.BLKGRPCE;
const ACS_ST = results.features[i].attributes.STATEFP;
const ACS_CNTY = results.features[i].attributes.COUNTYFP;
const ACS_TRCT = results.features[i].attributes.TRACTCE;
// push ACS_TRCT, ACS_ST, ACS_TRCT, ACS_CNTY to resulting
// array ctids if they don't present using `.includes` method.
if (!ctids.includes(ACS_TRCT)) ctids.push(ACS_TRCT);
if (!ctids.includes(ACS_ST)) ctids.push(ACS_ST);
if (!ctids.includes(ACS_CNTY)) ctids.push(ACS_CNTY);
if (!ctids.includes(ACS_TRCT)) ctids.push(ACS_TRCT);
}
You can use .find to check if the item is already present in the array ( will only work for primitive types )
var found = ctids.find(function(value) {
return ACS_TRCT === value;
});
if(!found) {
ctids.push(ACS_TRCT);
}

How to get one by one values(value in array) from Key Json?

I am getting values together from one key. Because in my case multiple values in array form come into the one key.
JSON
engine_data: {
internal: {
poling: {
account: [
"2009-38554",
"2009-38554"
],
secure: [
"2008-11833"
]
}
}
}
Javascript:
call.all('xyz').get(id).then(function(resp)
{
var res=resp.data;
var jsonData =
res.engine_data.internal.poling;
for(var i in jsonData){
if(i == "account")
{
alert(jsonData[i]);
alert(jsonData[i].length);
var account = jsonData[i].join(",")
$scope.acount = www.xyz/+account;
}if (i == "secure") {
var secure = jsonData[i].join(",")
$scope.secure = www.abc/+secure;
}
}
In my Json value in array form, So account (keys) has two value in array form. When I put in alert for printing then both value print together.
Screen Shot:
So I want to append these two value in www.xyz/ url.
Like out put result should be
www.xyz/2009-38554
www.xyz/2009-38554
But Right now I am getting
www.xyz/2009-38554,2009-38554
Share your ideas thanks in advance.
you can iterate over the array you get from account key and make all possible urls you can form values in array and you can make $scope.account an array and push all possible combinations, something like this:
for(var i in jsonData){
if(i == "account")
{
alert(jsonData[i]);
alert(jsonData[i].length);
$scope.account = [];
var account = jsonData[i];
for(var i=0; i<account.length; i++)
$scope.acount.push("www.xyz/"+account[i]);
}if (i == "secure") {
var secure = jsonData[i].join(",")
$scope.secure = www.abc/+secure;
}
}

Loop, get unique values and update

I am doing the below to get certain nodes from a treeview followed by getting text from those nodes, filtering text to remove unique and then appending custom image to the duplicate nodes.
For this I am having to loop 4 times. Is there is a simpler way of doing this? I am worried about it's performance for large amount of data.
//Append duplicate item nodes with custom icon
function addRemoveForDuplicateItems() {
var treeView = $('#MyTree').data('t-TreeView li.t-item');
var myNodes = $("span.my-node", treeView);
var myNames = [];
$(myNodes).each(function () {
myNames.push($(this).text());
});
var duplicateItems = getDuplicateItems(myNames);
$(myNodes).each(function () {
if (duplicateItems.indexOf($(this).text()) > -1) {
$(this).parent().append(("<span class='remove'></span>"));
}
});
}
//Get all duplicate items removing unique ones
//Input [1,2,3,3,2,2,4,5,6,7,7,7,7] output [2,3,3,2,2,7,7,7,7]
function getDuplicateItems(myNames) {
var duplicateItems = [], itemOccurance = {};
for (var i = 0; i < myNames.length; i++) {
var dept = myNames[i];
itemOccurance[dept] = itemOccurance[dept] >= 1 ? itemOccurance[dept] + 1 : 1;
}
for (var item in itemOccurance) {
if (itemOccurance[item] > 1)
duplicateItems.push(item);
}
return duplicateItems;
}
If I understand correctly, the whole point here is simply to mark duplicates, right? You ought to be able to do this in two simpler passes:
var seen = {};
var SEEN_ONCE = 1;
var SEEN_DUPE = 2;
// First pass, build object
myNodes.each(function () {
var name = $(this).text();
var seen = seen[name];
seen[name] = seen ? SEEN_DUPE : SEEN_ONCE;
});
// Second pass, append node
myNodes.each(function () {
var name = $(this).text();
if (seen[name] === SEEN_DUPE) {
$(this).parent().append("<span class='remove'></span>");
}
});
If you're actually concerned about performance, note that iterating over DOM elements is much more of a performance concern than iterating over an in-memory array. The $(myNodes).each(...) calls are likely significantly more expensive than iteration over a comparable array of the same length. You can gain some efficiencies from this, by running the second pass over an array and only accessing DOM nodes as necessary:
var names = [];
var seen = {};
var SEEN_ONCE = 1;
var SEEN_DUPE = 2;
// First pass, build object
myNodes.each(function () {
var name = $(this).text();
var seen = seen[name];
names.push(name);
seen[name] = seen ? SEEN_DUPE : SEEN_ONCE;
});
// Second pass, append node only for dupes
names.forEach(function(name, index) {
if (seen[name] === SEEN_DUPE) {
myNodes.eq(index).parent()
.append("<span class='remove'></span>");
}
});
The approach of this code is to go through the list, using the property name to indicate whether the value is in the array. After execution, itemOccurance will have a list of all the names, no duplicates.
var i, dept, itemOccurance = {};
for (i = 0; i < myNames.length; i++) {
dept = myNames[i];
if (typeof itemOccurance[dept] == undefined) {
itemOccurance[dept] = true;
}
}
If you must keep getDuplicateItems() as a separate, generic function, then the first loop (from myNodes to myNames) and last loop (iterate myNodes again to add the span) would be unavoidable. But I am curious. According to your code, duplicateItems can just be a set! This would help simplify the 2 loops inside getDuplicateItems(). #user2182349's answer just needs one modification: add a return, e.g. return Object.keys(itemOccurance).
If you're only concerned with ascertaining duplication and not particularly concerned about the exact number of occurrences then you could consider refactoring your getDuplicateItems() function like so:
function getDuplicateItems(myNames) {
var duplicateItems = [], clonedArray = myNames.concat(), i, dept;
for(i=0;i<clonedArray.length;i+=1){
dept = clonedArray[i];
if(clonedArray.indexOf(dept) !== clonedArray.lastIndexOf(dept)){
if(duplicateItems.indexOf(dept) === -1){
duplicateItems.push(dept);
}
/* Remove duplicate found by lastIndexOf, since we've already established that it's a duplicate */
clonedArray.splice(clonedArray.lastIndexOf(dept), 1);
}
}
return duplicateItems;
}

Why do the arrays I'm creating within my loop not contain all the values I've added after the loop completes?

I have an array in Java Script that I'm trying to split into two arrays using a test within a loop. The console is logging that the two objects are being stored, but after the loop finishes the inhaledArray array only contains one object.
for (var i=0; i<results.length; i++)
{
var inhaledArray = new Array();
var otherArray = new Array();
if(results[i].get('MedicationType') == "inhaled")
{
//inhaledArray is dumping results
console.log(results[i]);
inhaledArray.push(results[i]);
}
if(results[i].get('MedicationType') == "other")
{
otherArray.push(results[i]);
}
}
You are resetting the output at every iteration (by pointing the variable to a new array).
Move the array setup code outside of the loop.
Alex already answered your question, but here's a suggestion. If you ever have a bunch of arrays that store basically the same data, consider using an object instead:
var categories = {};
for (var i = 0; i < results.length; i++) {
var name = results[i].get('MedicationType');
if (name in categories) {
categories[name].push(results[i]);
} else {
categories[name] = [results[i]];
}
}
console.log(categories.inhaled);
console.log(categories.other);
That way, you can account for all of the category types without hard-coding anything.
this is because you are initializing the array inside the forloop, just move the Array initialization before the for loop like below
var inhaledArray = new Array();
var otherArray = new Array();
for (var i = 0; i < results.length; i++) {
if (results[i].get('MedicationType') == "inhaled") {
//inhaledArray is dumping results
console.log(results[i]);
inhaledArray.push(results[i]);
}
if (results[i].get('MedicationType') == "other") {
otherArray.push(results[i]);
}
}

Writing google Javascript similar to vlookup

ColumnA ColumnB
jhinz 115
tom 116
The idea behind this code is someone enters a number (lets say 116), the computer looks it up in column B and returns the name in column A (tom)
The only part I need help on for the code is the computer looking up the value in column 116.
I was trying to do a for loop with a nested if statement but it wasn't working.
Could someone help me?
in its simplest form and to see the working principle you could try this :
function findinB() {
var sh = SpreadsheetApp.getActiveSheet();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var last=ss.getLastRow();
var data=sh.getRange(1,1,last,2).getValues();// create an array of data from columns A and B
var valB=Browser.inputBox('Enter value to search in B')
for(nn=0;nn<data.length;++nn){
if (data[nn][1]==valB){break} ;// if a match in column B is found, break the loop
}
Browser.msgBox(data[nn][0]);// show column A
}
I figured that #Serge's function can be made slightly more modular and might be worth sharing.
/*
Imitates the Vlookup function. Receives:
1. sheet - A reference to the sheet you would like to run Vlookup on
2. column - The number of the column the lookup should begin from
3. index - The number of columns the lookup should cover.
4. value - The desired value to look for in the column.
Once the cell of the [value] has been found, the returned parameter would be the value of the cell which is [index] cells to the right of the found cell.
*/
function vlookup(sheet, column, index, value) {
var lastRow=sheet.getLastRow();
var data=sheet.getRange(1,column,lastRow,column+index).getValues();
for(i=0;i<data.length;++i){
if (data[i][0]==value){
return data[i][index];
}
}
}
Any suggestions or improvements are appreciated.
This could also be a good opportunity to start a repo for much needed Google Sheet API functions that are missing. I started a new repo which might someday turn into something more useful, if you're up to contributing your own custom made functions, please don't hesitate to PR.
Cheers!
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
//--//Dependent on isEmpty_()
// Script Look-up
/*
Benefit of this script is:
-That google sheets will not continually do lookups on data that is not changing with using this function as it is set with hard values until script is kicked off again.
-Unlike Vlookup you can have it look at for reference data at any Column in the row. Does not have to be in the first column for it to work like Vlookup.
-You can return the Lookup to Memory for further processing by other functions
Useage:
var LocNum = SpreadsheetApp.openById(SheetID).getSheetByName('Sheet1').getRange('J2:J').getValues();
Lookup_(Sheetinfo,"Sheet1!A:B",0,[1],"Sheet1!I1","n","y");
//or
Lookup_(Sheetinfo,"Sheet1!A:B",0,[1],"return","n","n");
//or
Lookup_(Sheetinfo,"Sheet1!A:B",0,[0,1],"return","n","n");
//or
Lookup_(Sheetinfo,"Sheet1!A:B",1,[0],"return","y","n");
//or
Lookup_(Sheetinfo,"Sheet1!A:G",4,[0],"Database!A1","y","y");
//or
Lookup_(Sheetinfo,LocationsArr,4,[0],"return","y","y");
*/
function Lookup_(Search_Key,RefSheetRange,SearchKey_Ref_IndexOffSet,IndexOffSetForReturn,SetSheetRange,ReturnMultiResults,Add_Note)
{
if(Object.prototype.toString.call(Search_Key) === '[object String]')
{
var Search_Key = new Array(Search_Key);
}
if(Object.prototype.toString.call(IndexOffSetForReturn) === '[object Number]')
{
var IndexOffSetForReturn = new Array(IndexOffSetForReturn.toString());
}
if(Object.prototype.toString.call(RefSheetRange) === '[object String]')
{
var RefSheetRangeArr = RefSheetRange.split("!");
var Ref_Sheet = RefSheetRangeArr[0];
var Ref_Range = RefSheetRangeArr[1];
var data = SpreadsheetApp.getActive().getSheetByName(Ref_Sheet).getRange(Ref_Range).getValues(); //Syncs sheet by name and range into var
}
if(Object.prototype.toString.call(RefSheetRange) === '[object Array]')
{
var data = RefSheetRange;
}
if(!/^return$/i.test(SetSheetRange))
{
var SetSheetRangeArr = SetSheetRange.split("!");
var Set_Sheet = SetSheetRangeArr[0];
var Set_Range = SetSheetRangeArr[1];
var RowVal = SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(Set_Range).getRow();
var ColVal = SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(Set_Range).getColumn();
}
var twoDimensionalArray = [];
for (var i = 0, Il=Search_Key.length; i<Il; i++) // i = number of rows to index and search
{
var Sending = []; //Making a Blank Array
var newArray = []; //Making a Blank Array
var Found ="";
for (var nn=0, NNL=data.length; nn<NNL; nn++) //nn = will be the number of row that the data is found at
{
if(Found==1 && /^n$/i.test(ReturnMultiResults)) //if statement for found if found = 1 it will to stop all other logic in nn loop from running
{
break; //Breaking nn loop once found
}
if (data[nn][SearchKey_Ref_IndexOffSet]==Search_Key[i]) //if statement is triggered when the search_key is found.
{
var newArray = [];
for (var cc=0, CCL=IndexOffSetForReturn.length; cc<CCL; cc++) //cc = numbers of columns to referance
{
var iosr = IndexOffSetForReturn[cc]; //Loading the value of current cc
var Sending = data[nn][iosr]; //Loading data of Level nn offset by value of cc
if(isEmpty_(Sending)) //if statement for if one of the returned Column level cells are blank
{
var Sending = "#N/A"; //Sets #N/A on all column levels that are blank
}
if (CCL>1) //if statement for multi-Column returns
{
newArray.push(Sending);
if(CCL-1 == cc) //if statement for pulling all columns into larger array
{
twoDimensionalArray.push(newArray);
var Found = 1; //Modifying found to 1 if found to stop all other logic in nn loop
break; //Breaking cc loop once found
}
}
else if (CCL<=1) //if statement for single-Column returns
{
twoDimensionalArray.push(Sending);
var Found = 1; //Modifying found to 1 if found to stop all other logic in nn loop
break; //Breaking cc loop once found
}
}
}
if(NNL-1==nn && isEmpty_(Sending)) //following if statement is for if the current item in lookup array is not found. Nessessary for data structure.
{
for(var na=0,NAL=IndexOffSetForReturn.length;na<NAL;na++) //looping for the number of columns to place "#N/A" in to preserve data structure
{
if (NAL<=1) //checks to see if it's a single column return
{
var Sending = "#N/A";
twoDimensionalArray.push(Sending);
}
else if (NAL>1) //checks to see if it's a Multi column return
{
var Sending = "#N/A";
newArray.push(Sending);
}
}
if (NAL>1) //checks to see if it's a Multi column return
{
twoDimensionalArray.push(newArray);
}
}
}
}
if(!/^return$/i.test(SetSheetRange))
{
if (CCL<=1) //checks to see if it's a single column return for running setValue
{
var singleArrayForm = [];
for (var l = 0,lL=twoDimensionalArray.length; l<lL; l++) //Builds 2d Looping-Array to allow choosing of columns at a future point
{
singleArrayForm.push([twoDimensionalArray[l]]);
}
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,singleArrayForm.length,singleArrayForm[0].length).setValues(singleArrayForm);
}
if (CCL>1) //checks to see if it's a multi column return for running setValues
{
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,twoDimensionalArray.length,twoDimensionalArray[0].length).setValues(twoDimensionalArray);
}
if(/^y$/i.test(Add_Note))
{
if(Object.prototype.toString.call(RefSheetRange) === '[object Array]')
{
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,1,1).setNote("VLookup Script Ran On: " + Utilities.formatDate(new Date(), "PST", "MM-dd-yyyy hh:mm a") + "\nRange: Origin Variable" );
}
if(Object.prototype.toString.call(RefSheetRange) === '[object String]')
{
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,1,1).setNote("VLookup Script Ran On: " + Utilities.formatDate(new Date(), "PST", "MM-dd-yyyy hh:mm a") + "\nRange: " + RefSheetRange);
}
}
SpreadsheetApp.flush();
}
if(/^return$/i.test(SetSheetRange))
{
return twoDimensionalArray
}
}
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
// Empty String Check
function isEmpty_(string)
{
if(Object.prototype.toString.call(string) === '[object Boolean]') return false;
if(!string) return true;
if(string == '') return true;
if(string === false) return true;
if(string === null) return true;
if(string == undefined) return true;
string = string+' '; // check for a bunch of whitespace
if('' == (string.replace(/^\s\s*/, '').replace(/\s\s*$/, ''))) return true;
return false;
}
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
I'm still new to JavaScript and Google Script but this seems to work.
And I'm sure there's a better way to limit the for-loop than data.length, but I don't know it.
function vlookup(row, col) {
var x=1, y=1;
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
for(x=1; x<data.length; x++){
while(data[x][0]===row){
for(y=1; y<data.length; y++){
while(data[0][y]===col){
var result = data[x][y]
return result;
}
}
}
}
}
I know I'm late to the party, but I built this script a while back. As expected, it's slow, but it performs vlookup as a script function. Range should be passed as a multidimensional array (array[row][col]). In Google Sheets you can place the cell range in the attributes and it will work:
function vlookupscript(search_key,range,index){
var returnVal = null;
for(var i in range) {
if(range[i][0] == search_key){
returnVal = range[i][(index-1)];
break;
}
}
return returnVal;
}

Categories

Resources