I'm having this string :
Hey I love #apple and #orange and also #banana
I would like to extract every words that start with the # symbol.
Currently I'm achieving it with this code :
var last = 0;
var n = 0;
var str = "Hey I love #apple and #orange and also #banana";
do{
n = str.indexOf("#", last);
if(n != -1){
//The code found the # char at position 'n'
last = n+1; //saving the last found position for next loop
//I'm using this to find the end of the word
var suffixArr = [' ', '#'];
var e = -1;
for(var i = 0; i < suffixArr.length;i++){
if(str.indexOf(suffixArr[i], n) != -1){
e = str.indexOf(suffixArr[i], n+1);
break;
}
}
if(e == -1){
//Here it could no find banana because there isn't any white space or # after
e = str.length; //this is the only possibility i've found
}
//extracting the word from the string
var word = str.substr(n+1, (e-1)-n);
}
}
while (n != -1);
How can I manage to find words starting with # and with a-Z characters only. If for example I have #apple! i should be able to extract apple
And also, as I mentionned in the code, how do I manage to get the word if it appears at the end of the string
(?:^|[ ])#([a-zA-Z]+)
Try this.Grab the capture.See demo.
https://regex101.com/r/wU7sQ0/18
var re = /(?:^|[ ])#([a-zA-Z]+)/gm;
var str = 'Hey I love #apple and #orange and #apple!# also #banana';
var m;
while ((m = re.exec(str)) != null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
}
You can use the regex /(^|\s)#[a-z]+/i and match it and then make use of Array.join(here it is being used internally when + "" executed) and replace all the # from the formed String and split on ,
var arr = (str.match(/(^|\s)#[a-z]+/i)+"").replace(/#/g,"").split(",");
If you also want to match test in Some#test, then remove the (^|\s) from the regex.
Related
I am creating a GDocs Apps Script to check my document to see if it is in Standard Pilish. I'd like to have the checker return both the position of the first error and the word that is incorrect. I can get the position of the first error in pi, but since the word list does not necessarily perfectly reflect that positioning.
For example, I used a modified quote from Peter Walder: "Two mathematicians accommodatingly promenade to tavern, quest everything". The error lies in the 8th word in the list, but the 10th position in pi.
This is the script I've landed at, and I originally tried to just words[positionOne] before realizing my counting error.
function pilishTranslate() {
var doc = DocumentApp.getActiveDocument();
var text = doc.getBody().getText();
// Remove quotation marks from the text
text = text.replace(/\"/g, "");
// Replace all non-letter characters with white space
text = text.replace(/[^a-zA-Z\s]/g, " ");
// Split the text into an array of words
var words = text.split(/\s+/);
// Count word length
var wordLengths = words.map(function(word) {
return word.length;
});
// Change 10 character counts to 0
wordLengths = wordLengths.map(function(length) {
return length === 10 ? 0 : length;
});
// Join character counts into single string
var wordLengthsString = wordLengths.join('');
// Create variable for pi
var decimal15 = '314159265358979'
// Find common prefix of strings a and b.
var prefix = function(a,b){
return a && a[0] === b[0] ? a[0] + prefix(a.slice(1), b.slice(1)) : '';
};
// Find index of first difference.
var diff = function(a,b){
return a===b ? -1 : prefix(a,b).length;
};
// actual test case
var tests = [
[wordLengthsString,decimal15],
];
// find first position of error
var positionOne = tests.map(test => diff(test[0], test[1]))
console.log(positionOne);
}
function checkPilish(text) {
// Remove quotation marks from the text
text = text.replace(/\"/g, "");
// Replace all non-letter characters with white space
text = text.replace(/[^a-zA-Z\s]/g, " ");
// Split the text into an array of words
var words = text.split(/\s+/);
// Create variable for pi
var decimal15 = '314159265358979'
let pi_index = 0;
// Loop over words
for (let i = 0; i < words.length; i++) {
// convert word length to Standard Pilish digits
let length_str = String(words[i].length);
if (length_str == '10') {
word_length = '0';
}
// check if this matches the current position in pi
if (decimal15.substr(pi_index, length_str.length) != length_str) {
return [i+1, words[i]];
}
pi_index += length_str.length;
}
return [];
}
console.log(checkPilish("Two mathematicians accommodatingly promenade to tavern, quest everything"));
console.log(checkPilish("Two mathematicians accommodatingly promenade to tavern, quest all"));
This is my first post so I hope im doing this correctly.
I am taking a coding class and we were asked to make a piece of code that will ask for the input of a phrase, and will return in the console that phrase with the capital letters moved to the front, but still in the same order. Then print to the console this reordered phrase. (We aren't allowed to use arrays)
For example:
Inputting "HeLLoTherE" would return "HLLTEeoher"
However the problem is im having issues understanding how to write this code. How can I make the code select these capital letters and move them to the front? using .toUpperCase()? How can i make that select the letter and move it in front of the rest?
If someone could show me an example of how this is done and explain it a little i would greatly appreciate it :)
You might just start with a the most straight forward algorithm to get something working.
let value = "HeLLoTherE";
let result = "";
for (let char of value) {
if (char >= "A" && char <= "Z") {
result += char;
}
}
for (let char of value) {
if (char >= "a" && char <= "z") {
result += char;
}
}
console.log(result);
You could then consolidate the 2 loops by combining the conditions.
let value = "HeLLoTherE";
let upper = "";
let lower = "";
for (let char of value) {
if (char >= "A" && char <= "Z") {
upper += char;
} else if (char >= "a" && char <= "z") {
lower += char;
}
}
console.log(upper + lower);
Another way of solving this would be to use regex.
var value = "HeLLoTherE";
var upper = value.replace(/[^A-Z]*/g, "");
var lower = value.replace(/[^a-z]*/g, "");
console.log(upper + lower);
Well, you are not able to use arrays, which makes it a little bit difficult, however you can still do sommething.
Although I'm using a for loop, I'm not actually using arrays. Since strings allows the [] operator, you can use an index to select each character of the string and check if it's lowercase or uppercase.
In addition, you said you need to mantain the order of uppercase letters, so you couldn't just do newStr = upper + newStr, because it would revert the original order. So, I used the string.prototype.substring() to insert the uppercase character where it should be.
const str = "HeLLoTherE";
const moveUpperToFront = (target) => {
// Strings are immutable in js, so you cannot move one character
// to the front without using a new string.
let newStr = "";
// Number of uppercase letters that appeared.
// It's necessary because you need to mantain the original order
let upperNumber = 0;
// Iterate each character from beginning
for (let i = 0; i < str.length; ++i) {
// Is there an uppercase letter?
if (str[i].charCodeAt() >= 65 && str[i].charCodeAt() <= 90) {
newStr =
newStr.substring(0, upperNumber) +
str[i] +
newStr.substring(upperNumber, newStr.length);
++upperNumber;
}
// No uppercase letter?
else
newStr += str[i];
}
return newStr;
};
console.log(moveUpperToFront(str));
Following a solution which uses a for...of loop to iterate the input. It splits the input into capital and lowercase literals and then merges back together:
const exampleLiteral = 'HeLLoTherE';
const isUppercase = (literal) => literal === literal.toUpperCase() && literal !== literal.toLowerCase();
const prefixCapitalLetters = (literal) => {
let capitalLetters = '';
let lowerLetters = '';
for (let letter of literal) {
if(isUppercase(letter)) {
capitalLetters = capitalLetters.concat(letter);
continue;
}
lowerLetters = lowerLetters.concat(letter);
};
return capitalLetters+lowerLetters;
}
console.log(prefixCapitalLetters(exampleLiteral));
This is really not a very hard problem:
function rearrange(str) {
let result = "";
for (let c of str)
if (c >= 'A' && c <= 'Z')
result += c;
for (let c of str)
if (c < 'A' || c > 'Z')
result += c;
return result;
}
console.log(rearrange("Hello World, It Is A Beautiful Morning!"));
Find the upper-case characters, and add them to a result string. Then go back and find the other characters, and add them at the end. By looping through without any sorting, just simple iteration from start to finish, the order is preserved (other than the upper-case stuff).
The truly hard part of this would be coming up with a way to detect "upper-case" letters across all of Unicode. Some languages (well, orthographies) don't have the concept at all. JavaScript has ways that are more and less convenient to deal with that, but I suspect for the classroom material the OP has available so far, given the nature of the original question, such regex trickery would probably be inappropriate for an answer.
This answer tries to achieve the desired objective without using "arrays". It does use back-ticks, but that can be replaced with a simple string-concatenation if required.
Code Snippet
// move upper-case letters while
// keeping relative order same
const capsWithOrder = str => {
// initialize result variables
let capsOnly = "", restAll = "";
// iterate over the given string input
for (let i = 0; i < str.length; i++) {
// if character at index "i" is upper-case
// then, concatenate character to "capsOnly"
// else, concatenate to "restAll"
if (str[i] === str[i].toUpperCase()) capsOnly += str[i];
else restAll += str[i];
};
// after iterating over all characters in string-input
// return capsOnly concatenated with restAll
return `${capsOnly}${restAll}`;
};
console.log(capsWithOrder("HeLLoTherE"));
Explanation
Inline comments added in the snippet above.
Something like this
const string1 = 'HeLLoTherE'
const transform = string => {
const lower = string.split('').filter(c => c.charCodeAt() > 'a'.charCodeAt())
const upper = string.split('').filter(c => c.charCodeAt() < 'Z'.charCodeAt())
return [...upper, ...lower].join('')
}
console.log(transform(string1))
I think that must be work.
const sort = [
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
'abcdefghijklmnopqrstuvwxyz'.split('')
]
function listByValue(string) {
string = [...string];
let ret = [];
for (let i in sort)
ret = [...ret,...string.filter(e=>sort[i].includes(e))];
return ret.join('')
}
I created a function that given any string will return the string with the first and last letter of each word capitalized. So far it works in some words, not on others, can someone help me figure out why?
function Capitalize(str) {
var spl = str.split(" ");
var words = [];
for (let i = 0; i < spl.length; i++) {
//For every word
for (let j = 0; j < spl[i].length; j++) {
//For every letter in each word
var word = spl[i];
var size = spl[i].length;
var firstLetterCapital = word.replace(word[0], word[0].toUpperCase()); //Creates new array
var LastLetterCapital = firstLetterCapital.replace(
word[size - 1],
word[size - 1].toUpperCase()
);
}
words.push(LastLetterCapital);
}
console.log(words.join(" "));
}
Capitalize("hello there");
It works when I type : Capitalize("my name is john smith"), but not with Capitalize("hello there")
I know it's a complete mess and probably a very bad way to do it, but I started programming a month ago so give me a break :)
#symlink has already explained why it is "HellO ThEre" instead of "Hello TherE". He also has given a solution to explicitly target first and last character of the string. I have accomplished not much different than already posted by members, except for .. "may be" a little more explanation.
You can break the entire problem in these four steps.
Get all the words into an array.
Create a function, that takes each word and targets first and last character, changes it and returns the changed word.
Apply a mapping step using the function created above (in step 2) to the entire array of words (obtained in step 1).
Join the transformed array, obtained in step 3, using a blank space as a separator.
I have written two functions that accomplish this task. I am sorry for long name of functions. It helps me keep track of things in a complex program (especially when I am in a hurry!).
Step 2 function
function Capitalize_FirstAndLast_One_Word(word){
// Split the string in array for easy access/manipulation by indexing
Split_String = word.split("")
// Target the first word
Split_String[0] = Split_String[0].toUpperCase();
// Target the last word
Split_String[Split_String.length - 1] = Split_String[Split_String.length - 1].toUpperCase();
// Join the array into a single word
Joined_Back = Split_String.join("")
return Joined_Back;
}
Step 1, 3 and 4 function
function Capitalize_Entire_String(str){
Regular_Exp = new RegExp(/\w+/g);
//Below is step 1
MatchedArray = str.match(Regular_Exp);
//Below is step 3
ConvertedArray = MatchedArray.map(Capitalize_FirstAndLast_One_Word);
// Below is step 4
ReturnedString = ConvertedArray.join(" ");
console.log(ReturnedString);
return ReturnedString;
}
Now you have everything. You can use the function like below.
Capitalize_Entire_String("hello there");
Capitalize_Entire_String("hello there this is a test");
Hope this helps. I am sorry if this turned out to be a redundant answer for you.
Reason your code don't work is the use of replace(). replace() will always replace the first character found.
There is absolutely no reason to run a nested loop. You can achieve this using a single loop.
function cap(str){
let spl = str.split(' ');
for(let i = 0; i < spl.length; i++){
let temp = spl[i];
temp = temp[0].toUpperCase() + temp.slice(1)
temp = temp.slice(0,-1) + temp[temp.length - 1].toUpperCase();
spl[i] = temp;
}
return spl.join(' ');
}
console.log(cap("a quick brown fox"))
An easier way is to use map() and template strings.
const cap = str => str
.split(' ')
.map(x => (
x.length === 1 ?
x.toUpperCase() :
`${x[0].toUpperCase()}${x.slice(1,-1)}${x[x.length -1].toUpperCase()}`)
)
.join(' ')
console.log(cap("a quick brown fox"))
To simplify the function, you could split the string into an array, map each word to the desired format, and join it together into a string again.
function Capitalize(str){
return str.split(" ").map((word) => word.charAt(0).toUpperCase() +
(word.length > 2 ? word.substring(1, word.length - 1) : "") +
(word.length > 1 ? word.charAt(word.length - 1).toUpperCase() : "")).join(" ");
}
console.log(Capitalize("i want to capitalize first and last letters"));
Congrats on starting out programming...
You can use this to achieve what you want to do
function capitalizeFirstAndLastLetters (str) {
const words = str.split(" "); // Split the string into words
const modified = [];
for (const word of words) {
if (word.length <= 2) {
modified.push(word.toUpperCase()); // If the word less than 3 characters, the whole word is capitalized
continue;
}
var firstCapital = word[0].toUpperCase(); // word[0] gets the first index of the string (I.e. the first letter of the word)
var lastCapital = word.slice(-1).toUpperCase(); // The slice function slices a portion of the word. slice(-1) gets the last letter
var middlePart = word.slice(1, -1); // slice(1, -1) means start slicing from the second index (I.e. 1) and ignore the last index
modified.push(firstCapital + middlePart + lastCapital);
}
return modified.join(" "); // Join each element in the modified array with a space to get the final string with each words first and last letters capitalized
}
capitalizeFirstAndLastLetters("hello there I am a boy"); // "HellO TherE I AM A BoY"
Try this, it worked for hello world because I guess you want the outcome to be HellO TherE right?:
function capitalize(str) {
var spl = str.split(" ");
var words = [];
for (let i = 0; i < spl.length; i++) {
//For every word
let changedWord = "";
for (let j = 0; j < spl[i].length; j++) {
//For every letter in each word
if(j == 0 || j == spl[i].length - 1) {
changedWord += spl[i][j].toUpperCase();
} else {
changedWord += spl[i][j].toLowerCase();
}
}
words.push(changedWord);
console.log(words);
}
console.log(words.join(" "));
}
capitalize("hello there");
ALSO: Make your functions name start with lowercase letter. Thats just how it is. Starting with uppercase letters usually are Classes. Just a quick tip
Maybe this does what you want, don't want to change much from your code:
function Capitalize(str) {
var spl = str.split(" ");
var words = [];
for (let i = 0; i < spl.length; i++) {
var word = spl[i];
var firstCapital = word[0].toUpperCase(); // get first character after capitalizing
var lastCapital = word.slice(-1).toUpperCase(); // get last character after capitalizing
var midOriginal = word.slice(1, -1);
words.push(firstCapital + midOriginal + lastCapital) // concat 3 parts
}
console.log(words.join(" "));
}
Capitalize("hello there");
This expression:
var LastLetterCapital = firstLetterCapital.replace(
word[size - 1],
word[size - 1].toUpperCase()
);
Is replacing the first occurrence of the character "e" in "There" with an uppercase "E".
Explanation
The replace() function first translates the first param: word[size - 1] to the literal character "e", then replaces the first occurrence of that character with the uppercase "E", resulting in the string "ThEre".
Solution
Use a regular expression as your first parameter instead, to ensure that the last character is targeted, regardless of whether or not that same character shows up anywhere else in the word:
var LastLetterCapital = firstLetterCapital.replace(/.$/, word[size - 1].toUpperCase());
function Capitalize(str) {
var spl = str.split(" ");
var words = [];
for (let i = 0; i < spl.length; i++) {
//For every word
var word = spl[i];
var size = spl[i].length;
for (let j = 0; j < size; j++) {
//For every letter in each word
var firstLetterCapital = word.replace(word[0], word[0].toUpperCase()); //Creates new array
var LastLetterCapital = firstLetterCapital.replace(/.$/, word[size - 1].toUpperCase());
}
words.push(LastLetterCapital);
}
console.log(words.join(" "));
}
Capitalize("hello there");
This should do the trick:
function Capitalize(str) {
return str.replace(/(\b\w|\w\b)/g, l => l.toUpperCase())
}
console.log(Capitalize('i want to be capitalized in a rather strange way'))
Explanation:
In the regular expression /(\b\w|\w\b)/g, \b means "word boundary" and \w means "word character", so (\b\w|\w\b) matches a word boundary followed by a word character OR a word character followed by a word boundary (i.e. the first and last character of words).
The matches of this expression are then passed to the inline function l => l.toUpperCase() (which itself is the second argument to replace) that capitalizes the passed letter.
the string type is immutable, so why don't you try to convert the string to an array like y = word.split('') and do y[0] = word.charAt(0).toUpperCase() and then convert back to string with y.join('')
Say for example I have the words below
THIS TEXT IS A SAMPLE TEXT
I am given character index 7.
Then I have to return index 1 when I split the sentence into words which is the index of the word that contains the index of character not 5 which matches the word that composes the index of character exactly but not the correct index where character lies.
basically I am trying to return the correct word index of where character lies (when split into words) with character index (when split with characters)
I thought I would reconstruct the word with something like below to find the word at the character
let curString = 'find a word from here';
let initialPositin = 5
let position = initialPositin
let stringBuilder = '';
while(position > -1 && curString.charAt(position) !== ' '){
console.log('run 1')
console.log(position);
stringBuilder = curString.charAt(position) + stringBuilder;
position --;
}
console.log(stringBuilder)
position = initialPositin + 1;
while(position < curString.length && curString.charAt(position) !== ' '){
console.log('run 2')
stringBuilder += curString.charAt(position);
position ++;
}
console.log(stringBuilder);
Then split the sentence into words then find all the index of the word that contains the word that I have constructed. Then go through all the found words and reconstruct the previous words to see if the index of the target character in the reconstruction matches the character position given.
It doesn't really feel efficient. Does anyone have better suggestions?
I prefer javascript but I can try to translate any other language myself
I think you could just count spaces that occurs before given index, something like
let curString = 'find a word from here';
let givenIndex = 9;
let spaceIndex = 0;
for (var i = 0; i < curString.length; i++) {
if(curString.charAt(i) == ' ') {
if (i < givenIndex) {
spaceIndex++;
} else {
// found what we need
console.log(spaceIndex);
}
}
}
Maybe you could build a function that returns the position of all spaces.
Then you can see where the character index fits in that list of space positions.
text = "THIS TEXT IS A SAMPLE TEXT"
indexes = []
current_word = 0
for i in range(0, len(text)):
if text[i] == ' ':
current_word += 1 # After a ' ' character, we passed a word
else:
indexes.append(current_word) # current character belongs to current word
You can build indexes array for once with this piece of code(written in Python3) then you can use it for every indice. If you want to count ' ' characters in indexes array as well, you can simple add them in for loop(in if statement).
I ended up using below code
let content = 'THIS IS A SAMPLE SENTENCE';
let target = 13;
let spaceCount = 0;
let index = 0;
while(index < target) {
if (content.charAt(index) === ' ') {
spaceCount++;
}
index++;
}
let splitContent = content.split(' ');
splitContent[spaceCount] = '#' + value
console.log(splitContent.join(' '))
Worked very nicely
Just like the answer from #miradham this function counts the spaces before the given index, but with builtin functions to count character occurrences.
function wordIndexOfCharacterIndexInString(index, string) {
const stringUpToCharacter = string.slice(0, index)
return (stringUpToCharacter.match(/ /g) || []).length
}
console.log(wordIndexOfCharacterIndexInString(7, "THIS TEXT IS A SAMPLE TEXT"))
I want to get the characters after # symbol till a space character.
for eg. if my string is like hello #world. some gibberish.#stackoverflow. Then I want to get the characters 'world' and 'stackoverflow'.
Here is what I have been trying.
var comment = 'hello #world. some gibberish.#stackoverflow';
var indices = [];
for (var i = 0; i < comment.length; i++) {
if (comment[i] === "#") {
indices.push(i);
for (var j = 0; j <= i; j++){
startIndex.push(comment[j]);
}
}
}
I can get the occurences of # and spaces and then trim that part to get my content but I'd like a better solution / suggestion for this, with without REGEX. Thanks in advance.
You can use this regex:
/#(\S+)/g
and grab captured groups using exec method in a loop.
This regex matches # and then \S+ matches 1 or more non-space characters that are grouped in a captured group.
Code:
var re = /#(\S+)/g;
var str = 'hello #world. some gibberish.#stackoverflow';
var m;
var matches=[];
while ((m = re.exec(str)) !== null) {
matches.push(m[1]);
}
document.writeln("<pre>" + matches + "</pre>");
PS: Note you will need to use
/#([^.\s]+)/g
if you don't want to capture DOT after word.