I am trying to make function on Google spreadsheet (JavaScript). My understanding of java script is very low but would like to know basics. any help would be appreciated.
I have information that has capital of last name and Name. but I want to make that capital of last name in the end of name and add gmail in the end. for example IJOSH make it JoshIgmail by using function
=Letter("IJOSH") -> "JoshIgmail" so start by moving capital (last name ) to the end, result in JoshI. Finally, add "gmail" in the end
function("letter"){
var letter;
return(etter+L+gmail)
}
You could get this rearrangement with a simple regular expression:
var _value = "IJOSH",
suffix = "gmail";
_value.replace( /^(.)(.*)$/, "$2$1" + suffix );
This results in "JOSH" being moved to the front, "I" being moved to the middle, and "gmail" being appended to the end of the string.
The pattern used is fairly straight-forward. The / and / indicate the beginning and end of the pattern. ^ and $ denote the front and back of the string, meaning we don't want to match on subsets, but on the entire string itself.
When we wrap something in ( and ) we create a capture class, allowing us to later reference it like $1 or $2 (depending on which capture class it was). In regex, . represents any character. We modify this in the second capture class with *, which means the previous pattern (. in this case) can be found 0 or more times.
do you mean something line:
function someTest() {
var str = "lJOSH";
var result = str.substr(1).toLowerCase() + str.substr(0, 1) + "gmail";
return result.charAt(0).toUpperCase() + result.slice(1);
}
console.log( someTest("lJOSH") ); //returns Joshlgmail
There are multiple ways, but heres that I would do:
//example call would be createEmail("IJOSH")
function createEmail(inputName) {
//String Assigned to a name variable
var name = inputName;
//Split it into individual letters as an array
var letters = name.split(""); //["I", "J", "O", "S", "H"];
//Treat it as a queue and remove first letter (assign it to a variable)
var fLetter = letters.shift();
//Push it to end of stack
letters.push(fLetter);
//Put them back together and the 'gmail' string to the end
var email = letters.join("") + "gmail"; //JOSHIgmail
return email;
}
This is a long typed way to do this, but a good way to learn about strings and arrays.
EDIT: Not the sexiest solution but hopefully easy to understand
Related
I'm receiving a list of files in an object and I just need to display a file name and its type in a table.
All files come back from a server in such format: timestamp_id_filename.
Example: 1568223848_12345678_some_document.pdf
I wrote a helper function which cuts the string.
At first, I did it with String.prototype.split() method, I used regex, but then again - there was a problem. Files can have underscores in their names so that didn't work, so I needed something else. I couldn't come up with a better idea. I think it looks really dumb and it's been haunting me the whole day.
The function looks like this:
const shortenString = (attachmentName) => {
const file = attachmentName
.slice(attachmentName.indexOf('_') + 1)
.slice(attachmentName.slice(attachmentName.indexOf('_') + 1).indexOf('_') + 1);
const fileName = file.slice(0, file.lastIndexOf('.'));
const fileType = file.slice(file.lastIndexOf('.'));
return [fileName, fileType];
};
I wonder if there is a more elegant way to solve the problem without using loops.
You can use replace and split, with the pattern we are replacing the string upto the second _ from start of string and than we split on . to get name and type
let nameAndType = (str) => {
let replaced = str.replace(/^(?:[^_]*_){2}/g, '')
let splited = replaced.split('.')
let type = splited.pop()
let name = splited.join('.')
return {name,type}
}
console.log(nameAndType("1568223848_12345678_some_document.pdf"))
console.log(nameAndType("1568223848_12345678_some_document.xyz.pdf"))
function splitString(val){
return val.split('_').slice('2').join('_');
}
const getShortString = (str) => str.replace(/^(?:[^_]*_){2}/g, '')
For input like
1568223848_12345678_some_document.pdf, it should give you something like some_document.pdf
const re = /(.*?)_(.*?)_(.*)/;
const name = "1568223848_12345678_some_document.pdf";
[,date, id, filename] = re.exec(name);
console.log(date);
console.log(id);
console.log(filename);
some notes:
you want to make the regular expression 1 time. If you do this
function getParts(str) {
const re = /expression/;
...
}
Then you're making a new regular expression object every time you call getParts.
.*? is faster than .*
This is because .* is greedy so the moment the regular expression engine sees that it puts the entire rest of the string into that slot and then checks if can continue the expression. If it fails it backs off one character. If that fails it backs off another character, etc.... .*? on the other hand is satisfied as soon as possible. So it adds one character then sees if the next part of the expression works, if not it adds one more character and sees if the expressions works, etc..
splitting on '_' works but it could potentially make many temporary strings
for example if the filename is 1234_1343_a________________________.pdf
you'd have to test to see if using a regular experssion is faster or slower than splitting, assuming speed matters.
You can kinda chain .indexOf to get second offset and any further, although more than two would look ugly. The reason is that indexOf takes start index as second argument, so passing index of the first occurrence will help you find the second one:
var secondUnderscoreIndex = name.indexOf("_",name.indexOf("_")+1);
So my solution would be:
var index = name.indexOf("_",name.indexOf("_")+1));
var [timestamp, name] = [name.substring(0, index), name.substr(index+1)];
Alternatively, using regular expression:
var [,number1, number2, filename, extension] = /([0-9]+)_([0-9]+)_(.*?)\.([0-9a-z]+)/i.exec(name)
// Prints: "1568223848 12345678 some_document pdf"
console.log(number1, number2, filename, extension);
I like simplicity...
If you ever need the date in times, theyre in [1] and [2]
var getFilename = function(str) {
return str.match(/(\d+)_(\d+)_(.*)/)[3];
}
var f = getFilename("1568223848_12345678_some_document.pdf");
console.log(f)
If ever files names come in this format timestamp_id_filename. You can use a regular expression that skip the first two '_' and save the nex one.
test:
var filename = '1568223848_12345678_some_document.pdf';
console.log(filename.match(/[^_]+_[^_]+_(.*)/)[1]); // result: 'some_document.pdf'
Explanation:
/[^]+[^]+(.*)/
[^]+ : take characters diferents of ''
: take '' character
Repeat so two '_' are skiped
(.*): Save characters in a group
match method: Return array, his first element is capture that match expression, next elements are saved groups.
Split the file name string into an array on underscores.
Discard the first two elements of the array.
Join the rest of the array with underscores.
Now you have your file name.
I would like to split a spreadsheet cell reference (eg, A10, AB100, ABC5) to two string parts: column reference and row reference.
A10 => A and 10
AB100 => AB and 100 ...
Does anyone know how to do this by string functions?
var res = "AA123";
//Method 1
var arr = res.match(/[a-z]+|[^a-z]+/gi);
document.write(arr[0] + "<br>" + arr[1]);
//Method 2 (as deceze suggested)
var arr = res.match(/([^\d]+)(\d+)/);
document.write("<br>" + arr[1] + "<br>" + arr[2]);
//Note here [^\d] is the same as \D
This is easiest to do with a regular expression (regex). For example:
var ref = "AA100";
var matches = ref.match(/^([a-zA-Z]+)([1-9][0-9]*)$/);
if (matches) {
var column = matches[1];
var row = Number(matches[2]);
console.log(column); // "AA"
console.log(row); // 100
} else {
throw new Error('invalid ref "' + ref + '"');
}
The important part here is the regex literal, /^([a-zA-Z]+)([1-9][0-9]*)$/. I'll walk you through it.
^ anchors the regex to the start of the string. Otherwise you might match something like "123ABC456".
[a-zA-Z]+ matches one or more character from a-z or A-Z.
[1-9][0-9]* matches exactly one character from 1-9, and then zero or more characters from 0-9. This makes sure that the number you are matching never starts with zero (i.e. "A001" is not allowed).
$ anchors the regex to the end of the string, so that you don't match something like "ABC123DEF".
The parentheses around ([a-zA-Z]+) and ([1-9][0-9]*) "capture" the strings inside them, so that we can later find them using matches[1] and matches[2].
This example is strict about only matching valid cell references. If you trust the data you receive to always be valid then you can get away with a less strict regex, but it is good practice to always validate your data anyway in case your data source changes or you use the code somewhere else.
It is also up to you to decide what you want to do if you receive invalid data. In this example I make the script throw an error, but there might be better choices in your situation (e.g. prompt the user to enter another value).
regex-pattern-to-match-any-substring-matching exact characters longer-than-two-characters-from-a-provided input,where ever exact string matches
Only pot or potato should be highlighted, instead of ota or ot, when user type pota and click search button.
Please find code below where matched string is highlighted.
// Core function
function buildRegexFor(find) {
var regexStr = find.substr(0,3);
for (var i = 1; i < find.length - 2; i++) {
regexStr = '(' + regexStr + find.substr(i+2,1) + '?|' + find.substr(i,3) + ')';
}
return regexStr;
}
// Handle button click event
document.querySelector('button').onclick = function () {
// (1) read input
var find = document.querySelector('input').value;
var str = document.querySelector('textarea').value;
// (2) build regular expression using above function
var regexStr = buildRegexFor(find);
// (3) apply regular expression to text and highlight all found instances
str = str.replace(new RegExp(regexStr, 'g'), "<strong class='boldtxt'>$1</strong>");
// (4) output
document.querySelector('span').textContent = regexStr;
document.querySelector('div').innerHTML = str;
};
consider "meter & parameter" as one string, if type meter in input box and click search button. meter should be highlighted as well as meter in parameter should highlight.Thanks in advance
Your for loop is set to go from i = 1, while i is less than find.length-2. find.length is 4. 4-2 is 2. So your for loop is set to go from i = 1 while i is less than 2. In other words, it's operating exactly once. I have no idea what you thought that for loop was going to do, but I'm betting that isn't it.
Prior to the for loop, regextr is set equal to the string pot (the first three characters of the find string. The first (and only) time through the for loop, it is set to a new value: the left paren, the existing value (pot), the fourth character of find (a), the question mark, the vertical bar, and three characters from find starting with the second. Put those together, and your regextr comes out to:
(pota?|ota)
That RegEx says to find either the string "pota" (with the a being optional, so "pot" also works) or the string "ota". So any instances of pota, pot, or ota will be found and highlighted.
If you just wanted "pota?", just eliminate the right half of that line inside the for loop. Better yet, replace the entire subroutine with just a line that appends the ? character to the find string.
So, as a relatively new programmer, I'm trying to create a very simple ASCII hangman game. I'm trying to figure out how to create a string of underscore's(_) based on the length of the word chosen.
For example, take the word Kaiser, I'd like to take, 'word.length(where word = "Kaiser")and convert it to "_ _ _ _ _ _`". Thanks in advance!
My first guess is something like this would work.
var underscored = string.split('').map(function(char) {
return char = '_ ';
}).join('');
Get every character in the string with the split function, and change the state of every character, using the map function. However, this will just give us an array. We need to perform type conversion again to turn it back to a string. To do this, we can use the join method. The delimiter we join is simply an empty string ''.
Another possibility is with the replace function
var underscored = string.replace(/./g, '_ ');
The regular expression here is very simple. The period . indicates any character. The global(g) flag means find all instances of the previous regex.
The second parameter of this function is what we want these characters to become. Since we want a space between underscores, this will be _.
Note that the replace method is not destructive. In other words, it does not modify the original array. You would need to store this in a separate variable. Because if you call string again, kaiser will be returned.
var str = "Kaiser";
var resStr = "";
for (i = 0; i < str.length; i++) {
resStr = resStr + " _";
}
You don't have to replace anything just create new string based on length of the first word, example :
var underscore_word = Array(word.length).join("_ ");
Take a look at Repeat Character N Times.
Hope this helps.
Is it possible to match a certain string once, and then multiple occurances of a string pattern multiple times, replacing each with itself, appended with another value (eg, line break)?
<!--HTML-->
<textarea id="i"></textarea>
JS
var s = "some-string-to-begin%a-b,c-d,e-f";
var re = /^(.*?)%(((\w+)\-(\w+)),?)*/g;
console.log(s.match(re)); //matches the whole string
var res = s.replace(re, "$1\n$2\n$3\n$4\n$5");
$("#i").val(res)
html:
<textarea>
some-string-to-begin
e-f
e-f
e
f
</textarea>
successfully matches the string, but I cannot seem to get a repetitive replacement of the word pairs.
JSBIN
You'll have to use a function replacement to do what you want:
s.replace( /^(.*?)%(.*)/, function(s,a,b) {
return a + '\n' + b.replace( /(\w+)-(\w+),?/g, '$1\n$2\n' );
});
My general philosophy is "why pull your hair out trying to make one uber-regex when you can easily accomplish your goal with two?" In this case, we match the greater string ("a-b,c-d,e-f"), then match the individual pairs and do the replacement.
Without knowing the greater context of your problem, it's hard to say, but it seems like you could accomplish your goal in a less complicated fashion by splitting and re-joining:
var parts = s.split( '%' );
var result = [ parts[0] ].concat( parts[1].split( /[,-]/ ) ).join( '\n' );
If your string will always be comma/percent delineated, you could do something like this:
var s = "some-string-to-begin%a-b,c-d,e-f",
replacement = s.split(/[%,]/g).join('\n'); // split by % or , and then join by linebreak
$("#i").val(replacement);
JSBIN
(Not sure if you're also trying to separate the 'a-b' into 'a\nb' as well.)