I have a JavaScript array that contains some words that cannot be used when requesting user accounts to be created.
I am trying to loop over the accounts requested and check them against a word filter. If they contain any of the words, the value is moved to an array of "Invalid Accounts".
// Create our arrays
var blacklist = ["admin", "webform", "spoof"];
var newAccounts = ["admin1#google.com", "interweb#google.com", "puppy#google.com"];
var invalidAccounts = [];
// I need to check if any of the new accounts have matches to those in the blacklist.
// admin1#google.com would need to be pushed into the invalidAccounts array because it
// contains the word admin. Although interweb contains the word web, it does not contain
// the full word, webform, so should be ignored.
// Loop over the blacklist array
for(var x = 0; x < blacklist.length; x++){
if(blacklist[x].indexOf(newAccounts) > -1){
alert(blacklist[x] + " is in the blacklist array");
// Push the newAccounts value into the invalidAccounts array since it contains
// a blacklist word.
} else {
alert('no matches');
}
}
What do I need to change in the above code to have it match the partial strings such as mentioned?
Fiddle of above code: https://jsfiddle.net/1qwze81o/
You probably won't need to use all of this but it should be helpful none the less:
var blacklist = ["admin", "webform", "spoof"];
var newAccounts = ["admin1#google.com", "interweb#google.com", "puppy#google.com"];
var invalidAccounts = [];
// transform each email address to an object of the form:
// { email: string, valid: boolean }
var accountObjects = newAccounts.map(function (a) {
return { email: a, valid: true };
});
// loop over each account
accountObjects.forEach(function (account) {
// loop over the blacklisted terms
blacklist.forEach(function (blacklisted) {
// check to see if your account email address contains a black listed term
// and set the valid property accordingly
account.valid = account.email.search(blacklisted) === -1;
});
});
// filter accountObjects, validAccounts will now contain an array of valid objects
var validAccounts = accountObjects.filter(function (a) {
return a.valid;
});
// back to the original type of a string array
var validEmailAddresses = validAccounts.map(function (a) {
return a.email;
});
A solution using javascript array native functions:
var invalidAccounts = newAccounts.filter(function(account){ // we need to filter accounts
return blacklist.some(function(word){ // and return those that have any of the words in the text
return account.indexOf(word) != -1
})
});
More info on: Array.filter and
Array.some
We need two loops to achieve this:
something like below:
// Loop over the blacklist array
for(var j = 0; x < newAccounts.length; j++){
for(var x = 0; x < blacklist.length; x++){
if(newAccounts[j].indexOf(blacklist[x]) > -1){
alert(blacklist[x] + " is in the blacklist array");
// Push the newAccounts value into the invalidAccounts array since it contains a blacklist word.
}else{
alert('no matches');
}
}
}
I fixed some of the things...
for (var x = 0; x < newAccounts.length; x++) // loop through new accounts
{
// for every account check if there is any match in blacklist array
for (var y = 0; y < blacklist.length; y++)
{
// if there is match do something
if (newAccounts[x].indexOf(blacklist[y]) > -1)
{
alert(newAccounts[x] + " is in the blacklist array");
break;
}
}
}
Here is the fiddle: https://jsfiddle.net/swaprks/n1rkfuzh/
JAVASCRIPT:
// Create our arrays
var blacklist = ["admin", "webform", "spoof"];
var newAccounts = ["admin1#google.com", "interweb#google.com", "puppy#google.com"];
var invalidAccounts = [];
for(var x = 0; x < newAccounts.length; x++){
for(var y = 0; y < blacklist.length; y++){
if( newAccounts[x].indexOf(blacklist[y]) > -1){
alert(blacklist[x] + " is in the blacklist array");
// Push the newAccounts value into the invalidAccounts array since it contains
// a blacklist word.
invalidAccounts.push(newAccounts[x]);
}else{
alert('no matches');
}
}
}
Related
I'm trying to build a collaborative doc editor and implement operational transformation. Imagine we have a string that is manipulated simultaneously by 2 users. They can only add characters, not remove them. We want to incorporate both of their changes.
The original string is: catspider
The first user does this: cat<span id>spider</span>
The second user does this: c<span id>atspi</span>der
I'm trying to write a function that will produce: c<span id>at<span id>spi</span>der</span>
The function I've written is close, but it produces c<span id>at<span i</span>d>spider</span> codepen here
String.prototype.splice = function(start, newSubStr) {
return this.slice(0, start) + newSubStr + this.slice(start);
};
function merge(saved, working, requested) {
if (!saved || !working || !requested) {
return false;
}
var diffSavedWorking = createDiff(working, saved);
var diffRequestedWorking = createDiff(working, requested);
var newStr = working;
for (var i = 0; i < Math.max(diffRequestedWorking.length, diffSavedWorking.length); i++) {
//splice does an insert `before` -- we will assume that the saved document characters
//should always appear before the requested document characters in this merger operation
//so we first insert requested and then saved, which means that the final string will have the
//original characters first.
if (diffRequestedWorking[i]) {
newStr = newStr.splice(i, diffRequestedWorking[i]);
//we need to update the merge arrays by the number of
//inserted characters.
var length = diffRequestedWorking[i].length;
insertNatX(diffSavedWorking, length, i + 1);
insertNatX(diffRequestedWorking, length, i + 1);
}
if (diffSavedWorking[i]) {
newStr = newStr.splice(i, diffSavedWorking[i]);
//we need to update the merge arrays by the number of
//inserted characters.
var length = diffSavedWorking[i].length;
insertNatX(diffSavedWorking, length, i + 1);
insertNatX(diffRequestedWorking, length, i + 1);
}
}
return newStr;
}
//arr1 should be the shorter array.
//returns inserted characters at their
//insertion index.
function createDiff(arr1, arr2) {
var diff = [];
var j = 0;
for (var i = 0; i < arr1.length; i++) {
diff[i] = "";
while (arr2[j] !== arr1[i]) {
diff[i] += arr2[j];
j++;
}
j++;
}
var remainder = arr2.substr(j);
if (remainder) diff[i] = remainder;
return diff;
}
function insertNatX(arr, length, pos) {
for (var j = 0; j < length; j++) {
arr.splice(pos, 0, "");
}
}
var saved = 'cat<span id>spider</span>';
var working = 'catspider';
var requested = 'c<span id>atspi</span>der';
console.log(merge(saved, working, requested));
Would appreciate any thoughts on a better / simpler way to achieve this.
I have a function here that is meant to check an element against a given array of regular expressions. The array that I am passing contains ten different regular expressions.
var regExAlphabet = /[a-z]/;
var regExNumbers = /[0-9]/;
var regExWhile = /while/;
var regExIf = /if/;
var regExElse = /else/;
var regExTrue = /true/;
var regExFalse = /false/;
var regExInt = /int/;
var regExString = /string/;
var regExBoolean = /boolean/;
var regexList = [regExAlphabet, regExNumbers, regExTrue, regExFalse,
regExInt, regExString, regExBoolean, regExWhile, regExIf, regExElse];
function loopThroughOptions(regexList, element) {
for (var i = 0; i < regexList.length; i++)
failSafe(regexList[i], element) // failSafe is defined but not shown
}
var aString = "a";
loopThroughOptions(regexList, aString);
When I run this, I am getting an uncaught typeError: cannot read property length of undefined in my loopThroughOptions function. Why is this happening? How can I fix it?
EDIT: It looks like I will need to post the failSafe function. It is quite long. Take a stab at it.
var tokenList = []; // list of discovered tokens
var substringsArray = []; // any strings that are not tokens go here
function substringsHandler(array) {
for (var i = 0; i < substringsArray.length; i++) {
for (var y = 0; y < regexList.length; y++) {
failSafe(regexList[y], substringsArray[i])
}
}
}
function findAMatch(value) {
if (value == "a")
console.log("matched a");
}
function findACharMatch(value) {
if (value == "a")
console.log("matched a");
}
function failSafe(regEx, element) {
if (regEx.test(element) && element.length > 1) { // if the token is there
var x = regEx.exec(element); // give us more information on the element
var value = x["0"]; // keep track of the value of the token
var index = x.index; // keep track of the index
var substring = value;
console.log(index);
console.log(substring.length);
console.log(element.length);
tokenList.push({
value: substring,
indexFound: index});
console.log(tokenList[0]);
if (index > 0 && index + substring.length - 1 < element.length) { // if we found a token in the middle of a string
console.log("Found token in the middle of the string.");
substringsArray.push({ // give us the half that comes before the match
value: element.substring(0, index),
indexFound: 0
});
substringsArray.push({ // give us the rest of the string that occurs after the match
value: element.substring(index + value.length),
indexFound: index + value.length
});
substringsHandler(substringsArray);
// all successful token finds get sent to tokenList to search for a match
// if nothing is found, then everything gets translated to characters or digits
} else if (index > 0 && index + substring.length - 1 == element.length) { // if there is more string to the left only
console.log("Found token on the right of the string.");
substringsArray.push({
value: element.substring(0, index), // compare these values using find a match later
indexFound: 0
})
} else if (index == 0 && substring.length < element.length) { // if there is more string to the right only
console.log("Found token on the left of the string.");
substringsArray.push({
value: element.substring(substring.length),
indexFound: substring.length
})
} else { // the token is the only input
console.log("The token consists of the entire string.");
}
} else if (regEx.test && element.length == 1) {
var x = regEx.exec(element); // give us more information on the element
var value = x["0"]; // keep track of the value of the token
var index = x.index; // keep track of the index
var substring = value;
tokenList.push({
value: value,
index: index
})
} else {
console.log("No match for regexp " + regEx + "trying the next one...");
return;
}
console.log(tokenList);
tokenList.sort(function(a, b) {
return a.indexFound - b.indexFound;
});
console.log(tokenList);
for (var i = 0; i < tokenList.length; i++) {
if (tokenList[i].value.length > 1)
findAMatch(tokenList[i].value);
else
findACharMatch(tokenList[i].value);
}
};
Ok, so I ran all of your showed code and it has an error, according to RegExp docs
If the match fails, the exec() method returns null.
So, in your code, you always take for granted that regEx.exec(element); will return an array (it supposes that the RegExp will match at least one element), which, at least in your examples, is false, and you are not handling that.
In short, the easiest way to get rid of this is by returning if x is null:
var x = regEx.exec(element);
if (!x) return // add this
Tested it, and no problem was thrown, only console output was matched a
So i have this array
[ 'vendor/angular/angular.min.js',
'vendor/angular-nice-bar/dist/js/angular-nice-bar.min.js',
'vendor/angular-material/modules/js/core/core.min.js',
'vendor/angular-material/modules/js/backdrop/backdrop.min.js',
'vendor/angular-material/modules/js/dialog/dialog.min.js',
'vendor/angular-material/modules/js/button/button.min.js',
'vendor/angular-material/modules/js/icon/icon.min.js',
'vendor/angular-material/modules/js/tabs/tabs.min.js',
'vendor/angular-material/modules/js/content/content.min.js',
'vendor/angular-material/modules/js/toolbar/toolbar.min.js',
'vendor/angular-material/modules/js/input/input.min.js',
'vendor/angular-material/modules/js/divider/divider.min.js',
'vendor/angular-material/modules/js/menu/menu.min.js',
'vendor/angular-material/modules/js/select/select.min.js',
'vendor/angular-material/modules/js/radioButton/radioButton.min.js',
'vendor/angular-material/modules/js/checkbox/checkbox.min.js',
'vendor/angular-material/modules/js/switch/switch.min.js',
'vendor/angular-material/modules/js/tooltip/tooltip.min.js',
'vendor/angular-material/modules/js/toast/toast.min.js',
'vendor/angular-clipboard/angular-clipboard.js',
'vendor/angular-animate/angular-animate.min.js',
'vendor/angular-aria/angular-aria.min.js',
'vendor/angular-messages/angular-messages.min.js',
'vendor/angular-ui-router/release/angular-ui-router.js',
'src/app/about/about.js',
'src/app/hekate.cfg.js',
'src/app/hekate.ctrl.js',
'src/app/hekate.module.js',
'src/app/home/home.js',
'src/app/user/dialog/user.signIn.ctrl.js',
'src/app/user/dialog/user.signIn.module.js',
'src/app/user/user.cfg.js',
'src/app/user/user.ctrl.js',
'src/app/user/user.module.js',
'src/common/services/toast.service.js',
'templates-common.js',
'templates-app.js'
]
And taking the following part from the above array as example:
[
'src/app/hekate.cfg.js',
'src/app/hekate.ctrl.js',
'src/app/hekate.module.js',
]
I want to sort it like
[
'src/app/hekate.module.js',
'src/app/hekate.cfg.js',
'src/app/hekate.ctrl.js',
]
So more specific of what i want is to find in that array where string is duplicated and after check if has at the end [.cfg.js, .ctrl.js, .module.js] and automatic order them to [.module.js, .cfg.js, .ctrl.js]
Can anyone please help me with that?
A single sort proposal.
var array = ['src/app/about/about.js', 'src/app/hekate.cfg.js', 'src/app/hekate.ctrl.js', 'src/app/hekate.module.js', 'src/app/home/home.js', 'src/app/user/dialog/user.signIn.ctrl.js', 'src/app/user/dialog/user.signIn.module.js', 'src/app/user/user.cfg.js', 'src/app/user/user.ctrl.js', 'src/app/user/user.module.js'];
array.sort(function (a, b) {
function replaceCB(r, a, i) { return r.replace(a, i); }
var replace = ['.module.js', '.cfg.js', '.ctrl.js'];
return replace.reduce(replaceCB, a).localeCompare(replace.reduce(replaceCB, b));
});
document.write('<pre>' + JSON.stringify(array, 0, 4) + '</pre>');
To prevent so much replaces, i suggest to have a look to sorting with map.
You can try something like this:
Algo:
Group based on path and store file names as value.
Check for existence of one of special file ".cfg.js"
Sort following list based on custom sort.
Loop over object's property and join key with values to form full path again.
If you wish to sort full array, you can sort keys itself and then merge path with names. I have done this. If you do not wish to do this, just remove sort function from final loop.
Sample
var data=["vendor/angular/angular.min.js","vendor/angular-nice-bar/dist/js/angular-nice-bar.min.js","vendor/angular-material/modules/js/core/core.min.js","vendor/angular-material/modules/js/backdrop/backdrop.min.js","vendor/angular-material/modules/js/dialog/dialog.min.js","vendor/angular-material/modules/js/button/button.min.js","vendor/angular-material/modules/js/icon/icon.min.js","vendor/angular-material/modules/js/tabs/tabs.min.js","vendor/angular-material/modules/js/content/content.min.js","vendor/angular-material/modules/js/toolbar/toolbar.min.js","vendor/angular-material/modules/js/input/input.min.js","vendor/angular-material/modules/js/divider/divider.min.js","vendor/angular-material/modules/js/menu/menu.min.js","vendor/angular-material/modules/js/select/select.min.js","vendor/angular-material/modules/js/radioButton/radioButton.min.js","vendor/angular-material/modules/js/checkbox/checkbox.min.js","vendor/angular-material/modules/js/switch/switch.min.js","vendor/angular-material/modules/js/tooltip/tooltip.min.js","vendor/angular-material/modules/js/toast/toast.min.js","vendor/angular-clipboard/angular-clipboard.js","vendor/angular-animate/angular-animate.min.js","vendor/angular-aria/angular-aria.min.js","vendor/angular-messages/angular-messages.min.js","vendor/angular-ui-router/release/angular-ui-router.js","src/app/about/about.js","src/app/hekate.cfg.js","src/app/hekate.ctrl.js","src/app/hekate.module.js","src/app/home/home.js","src/app/user/dialog/user.signIn.ctrl.js","src/app/user/dialog/user.signIn.module.js","src/app/user/user.cfg.js","src/app/user/user.ctrl.js","src/app/user/user.module.js","src/common/services/toast.service.js","templates-common.js","templates-app.js"];
// Create groups based on path
var o = {};
data.forEach(function(item) {
var lastIndex = item.lastIndexOf('/') + 1;
var path = item.substring(0, lastIndex);
var fname = item.substring(lastIndex);
if (!o[path]) o[path] = [];
o[path].push(fname);
});
var manualOrder= [".module.js", ".cfg.js", ".ctrl.js"];
Array.prototype.fuzzyMatch = function(search){
return this.some(function(item){
return item.indexOf(search)>-1;
});
}
Array.prototype.fuzzySearchIndex = function(search){
var pos = -1;
this.forEach(function(item, index){
if(search.indexOf(item)>-1){
pos = index;
}
});
return pos;
}
function myCustomSort(a,b){
var a_pos = manualOrder.fuzzySearchIndex(a);
var b_pos = manualOrder.fuzzySearchIndex(b);
return a_pos > b_pos ? 1 : a_pos < b_pos ? -1 : 0;
}
// Check for ".cfg.js" and apply custom sort
for (var k in o) {
if (o[k].fuzzyMatch(".cfg.js")) {
o[k].sort(myCustomSort);
}
}
// Merge Path and names to create final value
var final = [];
Object.keys(o).sort().forEach(function(item) {
if (Array.isArray(o[item])) {
final = final.concat(o[item].map(function(fn) {
return item + fn
}));
} else
final = final.concat(o[item]);
});
console.log(final);
First make an array for names like 'hekate'.
Then make an array for final results.
We need 3 searching loops for ctrls, cfgs and modules.
If string contains arrayWithNames[0] + '.module' push the whole record to new array that you created. Same with ctrls and cfgs.
var allItems = []; //your array with all elements
var namesArray = [];
var finalResultsArray = [];
//fill name array here:
for(var i=0; i<=allItems.length; i++){
//you have to split string and find the module name (like 'hekate'). i hope you know how to split strings
}
//sort by modules, cfgs, ctrls:
for(var i=0; i<=namesArray.length; i++){
if(allItems[i].indexOf(namesArray[i] + '.module') > -1) {
finalResultsArray.push(allItems[i]);
}
}
for(var i=0; i<=namesArray.length; i++){
if(allItems[i].indexOf(namesArray[i] + '.cfg') > -1) {
finalResultsArray.push(allItems[i]);
}
}
for(var i=0; i<=namesArray.length; i++){
if(allItems[i].indexOf(namesArray[i] + '.ctrl') > -1) {
finalResultsArray.push(allItems[i]);
}
}
//now finalResultsArray have what you wanted
You can provide your own compare function to array.sort (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
Write one that returns the correct order for modules, ctrls and cfgs:
It should first remove the suffixes, and if the rest is the same, use the correct logic to return the order according to the suffix. Otherwise return a value according to the alphabetical order.
Update
I didn't test this code (not is it finished), but it should look something like that:
arr.sort(function(a, b) {
if ((a.endsWith(".cfg.js") || a.endsWith(".ctrl.js") || a.endsWith(".module.js")) &&
(b.endsWith(".cfg.js") || b.endsWith(".ctrl.js") || b.endsWith(".module.js"))) {
var sortedSuffixes = {
".module.js": 0,
".cfg.js": 1,
".ctrl.js": 2
};
var suffixAIdx = a.lastIndexOf(".cfg.js");
if (suffixAIdx < 0) suffixAIdx = a.lastIndexOf(".ctrl.js");
if (suffixAIdx < 0) suffixAIdx = a.lastIndexOf(".module.js");
var suffixBIdx = b.lastIndexOf(".cfg.js");
if (suffixBIdx < 0) suffixBIdx = b.lastIndexOf(".ctrl.js");
if (suffixBIdx < 0) suffixBIdx = b.lastIndexOf(".module.js");
var prefixA = a.substring(0, suffixAIdx);
var prefixB = b.substring(0, suffixAIdx);
if (prefixA != prefixB)
{
return a.localeCompare(b);
}
var suffixA = a.substring(suffixAIdx);
var suffixB = b.substring(suffixBIdx);
return sortedSuffixes[suffixA] - sortedSuffixes[suffixB];
} else {
return a.localeCompare(b);
}
});
Update 2
Here is a fiddle (https://jsfiddle.net/d4fmc7ue/) that works.
Good morning.
Very new coder with little background. I need to merge data from a google spreadsheet into an email, without using an add-on. I borrowed this code from a site and I'm able to produce an email but it will only pull from the first email address column. I need to send an email to both the manager and director. Their email address will be stored in two separate columns with unique labels. I can't change the spreadsheet data as the spreadsheet is storing responses pulled from a survey form that is already in progress (example column layout below):
Name / Email Address / Director Name / Director Email Address / Response 1 / Response 2 / etc...
Everything I've researched will send an email from one column, but not two, or a "cc".
Below is the borrowed code. Would very much appreciate any help on how to modify the code to send the "response" data to both the Manager and Director in one email.
kind regards,
KA
function sendEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheets()[0];
var dataRange = dataSheet.getRange(2, 1, dataSheet.getMaxRows() - 1, 15);
var templateSheet = ss.getSheets()[1];
var emailTemplate = templateSheet.getRange("A1").getValue();
// Create one JavaScript object per row of data.
var objects = getRowsData(dataSheet, dataRange);
// For every row object, create a personalized email from a template and send
// it to the appropriate person.
for (var i = 0; i < objects.length; ++i) {
// Get a row object
var rowData = objects[i];
// Generate a personalized email.
// Given a template string, replace markers (for instance ${"First Name"}) with
// the corresponding value in a row object (for instance rowData.firstName).
var emailText = fillInTemplateFromObject(emailTemplate, rowData);
var emailSubject = "Data Survey";
MailApp.sendEmail(rowData.emailAddress, emailSubject, emailText);
}
}
// Replaces markers in a template string with values define in a JavaScript data object.
// Arguments:
// - template: string containing markers, for instance ${"Column name"}
// - data: JavaScript object with values to that will replace markers. For instance
// data.columnName will replace marker ${"Column name"}
// Returns a string without markers. If no data is found to replace a marker, it is
// simply removed.
function fillInTemplateFromObject(template, data) {
var email = template;
// Search for all the variables to be replaced, for instance ${"Column name"}
var templateVars = template.match(/\$\{\"[^\"]+\"\}/g);
// Replace variables from the template with the actual values from the data object.
// If no value is available, replace with the empty string.
for (var i = 0; i < templateVars.length; ++i) {
// normalizeHeader ignores ${"} so we can call it directly here.
var variableData = data[normalizeHeader(templateVars[i])];
email = email.replace(templateVars[i], variableData || "");
}
return email;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// The code below is reused from the 'Reading Spreadsheet data using JavaScript Objects'
// tutorial.
//
//////////////////////////////////////////////////////////////////////////////////////////
// getRowsData iterates row by row in the input range and returns an array of objects.
// Each object contains all the data for a given row, indexed by its normalized column name.
// Arguments:
// - sheet: the sheet object that contains the data to be processed
// - range: the exact range of cells where the data is stored
// - columnHeadersRowIndex: specifies the row number where the column names are stored.
// This argument is optional and it defaults to the row immediately above range;
// Returns an Array of objects.
function getRowsData(sheet, range, columnHeadersRowIndex) {
columnHeadersRowIndex = columnHeadersRowIndex || range.getRowIndex() - 1;
var numColumns = range.getEndColumn() - range.getColumn() + 1;
var headersRange = sheet.getRange(columnHeadersRowIndex, range.getColumn(), 1, numColumns);
var headers = headersRange.getValues()[0];
return getObjects(range.getValues(), normalizeHeaders(headers));
}
// For every row of data in data, generates an object that contains the data. Names of
// object fields are defined in keys.
// Arguments:
// - data: JavaScript 2d array
// - keys: Array of Strings that define the property names for the objects to create
function getObjects(data, keys) {
var objects = [];
for (var i = 0; i < data.length; ++i) {
var object = {};
var hasData = false;
for (var j = 0; j < data[i].length; ++j) {
var cellData = data[i][j];
if (isCellEmpty(cellData)) {
continue;
}
object[keys[j]] = cellData;
hasData = true;
}
if (hasData) {
objects.push(object);
}
}
return objects;
}
// Returns an Array of normalized Strings.
// Arguments:
// - headers: Array of Strings to normalize
function normalizeHeaders(headers) {
var keys = [];
for (var i = 0; i < headers.length; ++i) {
var key = normalizeHeader(headers[i]);
if (key.length > 0) {
keys.push(key);
}
}
return keys;
}
// Normalizes a string, by removing all alphanumeric characters and using mixed case
// to separate words. The output will always start with a lower case letter.
// This function is designed to produce JavaScript object property names.
// Arguments:
// - header: string to normalize
// Examples:
// "First Name" -> "firstName"
// "Market Cap (millions) -> "marketCapMillions
// "1 number at the beginning is ignored" -> "numberAtTheBeginningIsIgnored"
function normalizeHeader(header) {
var key = "";
var upperCase = false;
for (var i = 0; i < header.length; ++i) {
var letter = header[i];
if (letter == " " && key.length > 0) {
upperCase = true;
continue;
}
if (!isAlnum(letter)) {
continue;
}
if (key.length == 0 && isDigit(letter)) {
continue; // first character must be a letter
}
if (upperCase) {
upperCase = false;
key += letter.toUpperCase();
} else {
key += letter.toLowerCase();
}
}
return key;
}
// Returns true if the cell where cellData was read from is empty.
// Arguments:
// - cellData: string
function isCellEmpty(cellData) {
return typeof(cellData) == "string" && cellData == "";
}
// Returns true if the character char is alphabetical, false otherwise.
function isAlnum(char) {
return char >= 'A' && char <= 'Z' ||
char >= 'a' && char <= 'z' ||
isDigit(char);
}
// Returns true if the character char is a digit, false otherwise.
function isDigit(char) {
return char >= '0' && char <= '9';
}
According to the documentation : Mail App, the recipent represents the addresses of the recipients, separated by commas
So in order to send to several recipents, just make a string separated by comma:mike#example.com, mike2#example.com
You could pick the rows you want and do something like this:
MailApp.sendEmail(rowData[0].emailAddress + ',' + rowData[1].emailAdress, emailSubject, emailText);
how do I count the frequency of the elements in the array, I'm new to Javascript and completely lost, I have looked at other answers here but can't get them to work for me. Any help is much appreciated.
function getText() {
var userText;
userText = document.InputForm.MyTextBox.value; //get text as string
alphaOnly(userText);
}
function alphaOnly(userText) {
var nuText = userText;
//result = nuText.split("");
var alphaCheck = /[a-zA-Z]/g; //using RegExp create variable to have only alphabetic characters
var alphaResult = nuText.match(alphaCheck); //get object with only alphabetic matches from original string
alphaResult.sort();
var result = freqLet(alphaResult);
document.write(countlist);
}
function freqLet(alphaResult) {
count = 0;
countlist = {
alphaResult: count
};
for (i = 0; i < alphaResult.length; i++) {
if (alphaResult[i] in alphaResult)
count[i] ++;
}
return countlist;
}
To count frequencies you should use an object which properties correspond to the letters occurring in your input string.
Also before incrementing the value of the property you should previously check whether this property exists or not.
function freqLet (alphaResult) {
var count = {};
countlist = {alphaResult:count};
for (i = 0; i < alphaResult.length; i++) {
var character = alphaResult.charAt(i);
if (count[character]) {
count[character]++;
} else {
count[character] = 1;
}
}
return countlist;
}
If you can use a third party library, underscore.js provides a function "countBy" that does pretty much exactly what you want.
_.countBy(userText, function(character) {
return character;
});
This should return an associative array of characters in the collection mapped to a count.
Then you could filter the keys of that object to the limited character set you need, again, using underscore or whatever method you like.
Do as below:
var __arr = [6,7,1,2,3,3,4,5,5,5]
function __freq(__arr){
var a = [], b = [], prev
__arr.sort((a,b)=>{return a- b} )
for(let i = 0; i<__arr.length; i++){
if(__arr[i] !== prev){
a.push(__arr[i])
b.push(1)
}else{
b[b.length - 1]++
}
prev = __arr[i]
}
return [a , b]
}