I am currently trying to make a .replace function loop in javascript. What I am trying to do is replace a random character with a hyphen, but the part that I am struggling with is how to make it loop the replacing of the character to hyphen. Here is the code that I have so far:
var randHold;
var randomWord;
var randLetHold;
var dispWord;
var repLetHold;
var myWords = new Array("Spectrometer", "Bandwagonjghvyjh", "jvjyvyvilvyjlvyv",
"fruitjjyvtyvjv", "seventctcvtv", "weathertfhtcthc",
"undercfxdtfv"); // random letters to make words that have more than 10 letters
function level() {
randHold = parseInt((Math.random() * 6) + 1);//code to randomly pick a word from the above array
randomWord = myWords[randHold]; //code to call the random word from the array
randLetHold = (Math.random() * randomWord.length);//code to randomly pick a character from the random word chosen
repLetHold = randomWord.charAt(randLetHold);//code to call the random character
for (i = 1; i <= 3; i++) //loop to replace three random characters with a hyphen
{
dispWord = randomWord.replace(repLetHold," - ");//code to replace a random character with a hyphen
document.write(dispWord);//But all this does is display the word(with ONE hypenated character)three times.
}
}
Your code actually seems fine, the main issue is that you're declaring your random variables outside of your for loop. Doing this will only generate them once for the entire loop. Try this instead:
var dispWord;
var myWords = new Array("Spectrometer", "Bandwagonjghvyjh", "jvjyvyvilvyjlvyv",
"fruitjjyvtyvjv", "seventctcvtv", "weathertfhtcthc",
"undercfxdtfv"); // random letters to make words that have more than 10 letters
function level() {
for (i = 1; i <= 3; i++) //loop to replace three random characters with a hyphen
{
var randHold = parseInt((Math.random() * 6) + 1);//code to randomly pick a word from the above array
var randomWord = myWords[randHold]; //code to call the random word from the array
var randLetHold = (Math.random() * randomWord.length);//code to randomly pick a character from the random word chosen
var repLetHold = randomWord.charAt(randLetHold);//code to call the random character
dispWord = randomWord.replace(repLetHold," - ");//code to replace a random character with a hyphen
document.write(dispWord);//But all this does is display the word(with ONE hypenated character)three times.
}
}
For 3 random characters to be hyphenated in the word, you want something like this.
<div id="result"></div>
var myWords = ["Spectrometer", "Bandwagonjghvyjh", "jvjyvyvilvyjlvyv",
"fruitjjyvtyvjv", "seventctcvtv", "weathertfhtcthc",
"undercfxdtfv"]; // random letters to make words that have more than 10 letters
var randomWord;
var dispWord;
var repLetHold = [];
function uniqueCount(str) {
var unique = [];
Array.prototype.forEach.call(str, function (value) {
if (unique.indexOf(value) === -1) {
unique.push(value);
}
});
return unique.length;
}
function level() {
var randHold = Math.floor(Math.random() * myWords.length);
dispWord = randomWord = myWords[randHold];
if (uniqueCount(randomWord) > 2) {
var count = 0,
temp1,
temp2;
while (count < 3) {
temp1 = Math.floor(Math.random() * dispWord.length);
temp2 = dispWord.charAt(temp1);
if (temp2 !== "-" && repLetHold.indexOf(temp2) === -1) {
dispWord = dispWord.replace(new RegExp(temp2, "g"), "-");
repLetHold[count] = temp2;
count += 1;
}
}
}
document.getElementById("result").textContent = dispWord;
}
level();
console.log(randomWord, repLetHold);
on jsfiddle
If you use a regular expression, you can replace all instances at once with the g (global) flag. For example:
var str = "this is a mass Spectrometer, which is a Spectrometer to detect the spectra of different masses";
var replaced = str.replace(/Spectometer/g, 'something');
// "this is a mass something, which is a something to detect the spectra of different masses";
Just keep in mind that some characters must be escaped inside regular expressions.
http://jsfiddle.net/zt8mp/
If i got the question right:
randomWord.replace(new RegExp(repLetHold,'g')," - ")
replaces all occurences of repLetHold (as long as it is not made of special regex characters)
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"));
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('')
I am trying to build a hangman game and I need help with the logic. I am in a beginners class so I want to try and build this using beginners syntax. What I am trying to figure out
2) My issue is I need to display dashes (-) that represent blank lines and they need to be the same length of the randomly chosen word. In addition, every time a letter is correctly guessed, I need to replace the dashes with the correctly chosen letter. A solution I have thought of is making an empty array and then assigning it the dash signs in a for loop that is the length of the string and then replacing the indexes of specific dashes with matched letters, but I am not sure if this will work.
var randomWords = ['rock', 'paper', 'scissors'];
var numWins = 0;
var chosenWord = randomWords[Math.floor(Math.random() * randomWords.length)];
document.onkeyup = function(event) {
// var userGuess = String.fromCharCode(event.keyCode).toLowerCase();
var dashes = "";
for (var x = 0; x < chosenWord.length; x++) {
dashes += " - ";
// document.getElementById("word").innerHTML = blankLines;
// document.getElementById("word").innerHTML = ;
}
document.getElementById("word").innerHTML = dashes;
Trying to replace a dash with a letter in lines below. But both commented out code and non commented out codes work. That is why I am thinking of using an empty array but not sure if I can fill it with data using a foor loop
// for (x = 0; x < chosenWord.length; x++)
// {
// dashes[x] = "a";
// dahes.charAt(x) = 'a';
// }
dashes.charAt(0) = "a";
document.getElementById("test2").innerHTML = dashes;
This one should work. In the first case (if there's a white space in the word) it will display a whitespace. In the second case, it will replace every letter of the word with a dash.
var dashes = "";
for (i = 0; i < chosenWord.length; i++) {
if (chosenWord.charAt(i) == " ") {
dashes += " ";
} else {
dashes += "-";
}
}
I have to replace the digits in the first (n-4) characters of credit card with '*'.
I am using following three lines of code.
var cardnumber = '1A2C3GF4DS84Ff';
last4digits = cardNumber.substring(cardNumber.length-4);
prevdigits = cardNumber.substring(0, cardNumber.length-4).replace(/[0-9]/g,'*');
$cache.cardNumber.val( prevdigits + last4digits);
Just wondering can I do it in just one line of code by using regex.
Use a look-ahead to ensure that there are at least four remaining characters after the digit. In other words, digits within the last four characters will not match:
var regexp = /\d(?=....)/g;
> cardnumber.match(regexp)
< ["1", "2", "3", "4"]
To replace with asterisks:
> cardnumber.replace(regexp, '*')
< "*A*C*GF*DS84Ff"
Information on look-aheads is here.
From here I got this code.
var text = '1ab2cb3cd4ab5cb6cd7';
var matches = text.match(/(\d)/g);
for (i=0; i<matches.length; i++) {
alert(matches[i]);
}
Actually, they wanted to extract digits too. I don't need to change the regex.
You can limit it to 5 by making the loop start with:
for (i=0; i<matches.length && i < 5; i++){
Just use (\d) and check it programmatically afterwards.
var y= x.replace(/\D/g, '').substring(0, 5);
The .replace() function can use a function as the replacement, and it will be called for each match. It can keep a counter and return something different based on the counter.
var str = '1A2C3GF4DS84Ff';
var digits = 0;
var newstr = str.replace(/\d/g, function(match) {
if (digits++ < 4) {
return '*';
} else {
return match;
}
});
document.write(newstr);
looks like following one does the job You need:
var text= '1A2B3C4D5E6F',
n = 5;
text = text.replace(/\d/g, function ($1){
return n-- ?'*' : $1
});
I have an input field and a textarea in a form. For each of those two fields I'd like to count the number of words, number of dots, and number of words longer than 7 characters.
I've already got the code for the two first numbers (number of words and number of dots), but I can't figure out how to count the number of words longer than 7 characters in each of the fields.
Can anyone help me out with this one?
Here is my current code (fiddle):
var titleElem = $('#title');
var numberOfWords = countWords(titleElem);
var numberOfDots = countDots(titleElem);
function countWords(input) {
var a, z, inputValue, total;
inputValue = input.val();
total = 0;
a = inputValue.replace(/\s/g, ' ');
a = a.split(' ');
for (z = 0; z < a.length; z++) { if (a[z].length > 0) total++; }
return total;
}
function countDots(input) {
var inputVal;
inputVal = input.val();
return inputVal.split(".").length - 1;
}
It depends what you classify as a word. Does that include hyphens/apostrophes? You could use a simple regex for this:
var wordCount = $("input").val().match(/[\w0-9]{8,}/gi).length
The {8,} ensures that it only captures words more than 7 characters in length.