I am using this function to build a pig latin translator and seem to have everything figured out except for the .trim() part. What should I do different?
function ParseText()
{
var myText = "asdf\n hat\n cat dog\n apple";
var lines = myText.split("\n");
var results = "";
for (var i = 0, len = lines.length; i < len; i++) {
lines[i].trim();
var words = lines[i].split(" ");
for (var j = 0, lenght = words.length; j < lenght; j++) {
var word = words[j];
if (word.charAt(0) == "a" || word.charAt(0) == "e" || word.charAt(0) == "i" || word.charAt(0) == "o" || word.charAt(0) == "u" || word.charAt(0) == "y")
{
results = results + word + "ay ";
}else {
var mutated = word.substring(1, word.length);
mutated = mutated + word.charAt(0)+ "ay ";
results = results + mutated;
}
}
results = results + "\n";
}
return results;
}
On the line lines[i].trim(); nothing seems to happen. the whitespace still becomes a \n item in the split array.
What should I change to remove the whitespace?
lines[i].trim(); does NOT modify the current string (see the doc here). It returns a new string.
If you want to trim the current string, then you need to do this:
lines[i] = lines[i].trim();
As per comments, here's very basic version of pig latin using regex that works with lowercase strings but it can be adjusted to handle mixed lower and upper case:
function pigLatin(str) {
return str
.toLowerCase() // make sure string is lowercase
.replace(/\b[aeiuo]\w+\b/g, '$&way') // starts with vowel
.replace(/\b([^aeiou\s])(\w+)\b/g, '$2$1ay'); // starts with consonant
}
// Example:
var str = 'hello world egg plant yellow';
console.log(pigLatin(str)); //=> "ellohay orldway eggway lantpay ellowyay"
Related
I need to implement the .split method in my own way without using prebuilt functions. The method should receive a string divided into 2 sentences by a dot and divide them through a separator.
For example, there is this string:
'word wooord wooooooooord wooooooord. wooooooooord woooooord woooord wooooooooord', separator in this case: '. '
The result should be:
['word wooord wooooooooord wooooooord", "wooooooooord woooooord woooord wooooooooord']
I tried to implement it myself, the first problem I encountered is that the words from the string are added character by character to the new array. The second problem is that the output is still a string even though I declared an array earlier.
function split(str, splitter){
let arrSent = []
for (let i = 0; i < str.length; i++){
if (str[i] != splitter){
arrSent += str[i]
}
}
return arrSent
}
console.log(split('word wooord wooooooooord wooooooord. wooooooooord woooooord woooord wooooooooord', '. '))
Since the delimiter can have more than one character, you need a system to upfront collect a sample of characters (of the same length as the delimiter) to be then compared with the delimiter:
const split = (str, delimiter) => {
// If delimiter is empty string just return an array of characters
if (delimiter === "") return [...str];
const len = delimiter.length;
const iter = str.length - len + 1; // max needed iterations
const arr = [""]; // Prefill it with empty string
let idx = 0; // arr insertion pointer
for (let i = 0; i < iter; i++) {
// Collect len chars from str as a sample
// to compare with the delimiter:
let sample = "";
for (let x = i; x < i + len; x++) {
sample += str[x];
}
const isSplit = sample === delimiter;
const isEnded = i === iter - 1;
if (isSplit) {
i += len - 1; // Consume splitted characters
idx += 1; // Increment arr pointer
arr[idx] = ""; // Prepare the new array key as empty string
} else {
// If loop ended append the entire sample.
// Otherwise, append a single character:
arr[idx] += isEnded ? sample : str[i];
}
}
return arr
}
console.log(split("word. etc", ". "));
console.log(split("word. etc. ", ". "));
console.log(split(". word yep. . etc. ", ". "));
console.log(split("word", ". "));
console.log(split("word", "word"));
console.log(split("word", ""));
console.log(split("", ""));
above, idx (starting at 0) is used as the output's arr insertion pointer. The idx is incremented if the sample matches the delimiter. Also, if there's a match, we need to skip iterations i += len, to not include the delimiter in the output array.
To test, create many examples and right before return arr; use console.log(JSON.stringify(arr) === JSON.stringify(str.split(delimiter))); - it should return true for all the submitted tests.
How to correct the second capital letter of each word into lower case after entering the third letter in lower case?
Example:
"INput" will be corrected into "Input" (since the first and second letter are capital letters)
"INP" will not be corrected.
A function that converts a string would suffice:
function autoCorrect(input) {
return "corrected input";
}
My question is different to existing posts like
Using Javascript, how to capitalize each word in a String excluding
acronyms
Is there a way to ignore acronyms in a title case method
Convert string to Title Case with JavaScript
I don't want to convert a string to title case in such a way that every new word begins with a capital(uppercase) letter but correct two consecutive upper case letters at the beginning of each word.
This seems to work, even if it is not the most elagant solution. Suggestions for improvement are welcome.
String.prototype.isUpperCase = function() {
return this.toString() === this.toUpperCase();
}
var str = "SOme Text THat NO YEs END";
var str2 = str[0] || '';
for (var i = 0; i < str.length; i++) {
const next1 = str[i + 1] || '';
const next2 = str[i + 2] || '';
if (str[i].isUpperCase() && next1.isUpperCase() && !next2.isUpperCase()) {
str2 += str[i+1].toLowerCase() || '';
} else {
str2 += str[i+1] || '';
}
}
console.log(str2);
It sounds like a regular expression is what you need.
The following regular expression matches word characters is in the range A-Z (ie. English uppercase) if that uppercase character is preceded by another word character at the start of a word (negative lookahead assertion (?<=\b\w)) and if that uppercase character is succeeded by one or more lowercase English word characters (lookahead assertion (?=[a-z]+)).
Does this do what you want?
const PATTERN = /(?<=\b\w)([A-Z])(?=[a-z]+)/gu
const fix = (s) =>
s.replaceAll(PATTERN, (_, match) => match.toLowerCase())
console.log(fix('As I aPproached the IBM building, I was asked for ID. Note ALSo.')) // 'As I approached the IBM building, I was asked for ID. Note ALSo.'
Just remove the first two lines, (improvement)
var str = "SOme Text THat NO YEs END";
var str2 = str[0] || '';
for (var i = 0; i < str.length; i++) {
const next1 = str[i + 1] || '';
const next2 = str[i + 2] || '';
if (str[i].isUpperCase() && next1.isUpperCase() && !next2.isUpperCase()) {
str2 += str[i+1].toLowerCase() || '';
} else {
str2 += str[i+1] || '';
}
}
console.log(str2);
I have a function where I am iterating through a given string, alternating the capitalisation of each character and concatenating it to variable alt.
In order to loop through this properly, I have removed spaces from the original string. But I need to add them back at the end of the function.
function alternatingCaps(str) { // 'hello world'
let words = str.toLowerCase().split(' '); // ['hello','world']
str = words.join(''); // 'helloworld'
let alt = '';
for(let i = 0; i < str.length; i++) {
if(i % 2 === 0)
alt += str[i].toUpperCase();
else
alt += str[i].toLowerCase();
}
return alt;
}
console.log(alternatingCaps('hello world'));
/* Output: "HeLlOwOrLd"
Wanted output: "HeLlO wOrLd" */
Once alt contains a string included as a value in the words array, I want to add a space at the end of the word.
Here was my attempt:
words.forEach(function(word) {
if(alt.toLowerCase().includes(word) && word[word.length - 1] === alt[i].toLowerCase())
alt += ' ';
});
It checks if any of the words in the words array are present in the alt string and if the current character iteration of the string corresponds to the last letter in the word. If so, it adds a space to the string.
But this does not work as intended.
> Output: "HeLlO wOr Ld"
> Wanted output: "HeLlO wOrLd"
I also imagine this would cause problems with duplicate letters. How can I accomplish my goal?
You shouldn't join your words. Keep them as separate elements in the words array then you can loop through that array applying you function to each element.
function alternatingCaps(str) { // 'hello world'
let words = str.toLowerCase().split(' '); // ['hello','world']
const alts = words.map(word => capitalizeEvens(word));
return alts.join(' ');
function capitalizeEvens(word) {
let alt = '';
for(let i = 0; i < word.length; i++) {
if(i % 2 === 0)
alt += word[i].toUpperCase();
else
alt += word[i].toLowerCase();
}
return alt;
}
console.log(alternatingCaps('hello world'));
You can iterate through your string one char at a time. Then, check whether the characters is an actual word character. If so, alternate the capitalization, if not, add it to the output as it is:
function altCaps(input) {
var result = '';
var cap = false;
for (var i = 0; i < input.length; i++) {
var c = input[i];
result += /\w/.test(c) ? (cap = !cap) ? c.toUpperCase() : c.toLowerCase() : c;
}
return result;
}
UPDATE: The legible code
function altCaps(input) {
var result = '';
var cap = false;
for (var i = 0; i < input.length; i++) {
var c = input[i];
if (/\w/.test(c)) { // check if char is a "word character" (i.e. letter)
cap = !cap; // toggle next capitalization
if (cap) // if it should capitalize
result += c.toUpperCase(); // add uppercase letter
else
result += : c.toLowerCase(); // add lowercase letter
} else {
result += c; // no letter, so add character as is.
}
}
return result;
}
I have two strings. The first is normal string, the second I want to be a reversed string like first one, but in the console I didn't get the look of like first one listed by commas. How can I fix that ?
Normal string -
Revered string -
window.onload = function(){
inputBox = document.getElementById("myText");
btn = document.getElementById('sub');
btn.addEventListener("click",function(event){
event.preventDefault();
findPalindromes(inputBox.value);
});
str = inputBox.value;
function findPalindromes(str) {
var words = str.split(" ");
for (var i = 0; i < words.length - 1; i++) {
words[i] += " ";
}
console.log(words);
var newString = "";
for (var i = words.length - 1; i >= 0; i--) {
newString += words[i];
}
console.log(newString);
}
}
If you really just want to find out if a string is a palindrome, you can do something as simple as this:
function isPalindrome(str) {
return str.toLowerCase() === str.toLowerCase().split('').reverse().join('');
}
The first for loop is not necessary. You do not need to concatenate a space character " " to the element of the array, where the variable assignment i
var i = 0;
and condition
i < words.length - 1;
stops before reaching last element of array.
var newString = "";
for (var i = words.length - 1; i >= 0; i--) {
newString += words[i] + " ";
}
console.log(newString);
In your "normal" string example, you're printing words to the console. Let's first look at what words is: var words = str.split(" ");
The String.split() function returns an array of strings. So your "normal" string is actually an array of strings (The brackets [] and comma separated strings in the console output indicate this).
In the second example, you're logging newString. Let's look at where it comes from: var newString = "";
newString is a String. If you want it to be an array of strings like words, you would declare it with var newString = [];. Arrays do not support += so newString += words[i]; would become newString.push(words[i]);
The above explains how to get newString to behave like words, the code you've written is not looking for a palindrome word, but rather a palindrome sentence: "Bob is Bob" is not a palindrome (reversed it is "boB si boB") but it could be a Palindrome sentence (if such a thing exists).
Thanks to all, I wrote this solution for the problem. I hope this is the right answer.
window.onload = function(){
inputBox = document.getElementById("myText");
btn = document.getElementById('sub');
btn.addEventListener("click",function(event){
event.preventDefault();
findPalindromes(inputBox.value);
});
str = inputBox.value;
function findPalindromes(str) {
var words = str.split(" "),
newString = [];
for (var i = 0; i < words.length - 1; i++) {
if ((words[i] === words[i].split('').reverse().join('')) === true) {
newString.push(words[i]);
}
}
console.log(newString);
}
}
var words = " ";
function reverse_arr(arr){
var i = arr.length - 1;
while(i >= 0){
words += a[i] + " ";
i--;
}
return words;
}
What's the best and most efficient way to count keywords in JavaScript? Basically, I'd like to take a string and get the top N words or phrases that occur in the string, mainly for the use of suggesting tags. I'm looking more for conceptual hints or links to real-life examples than actual code, but I certainly wouldn't mind if you'd like to share code as well. If there are particular functions that would help, I'd also appreciate that.
Right now I think I'm at using the split() function to separate the string by spaces and then cleaning punctuation out with a regular expression. I'd also want it to be case-insensitive.
Cut, paste + execute demo:
var text = "Text to be examined to determine which n words are used the most";
// Find 'em!
var wordRegExp = /\w+(?:'\w{1,2})?/g;
var words = {};
var matches;
while ((matches = wordRegExp.exec(text)) != null)
{
var word = matches[0].toLowerCase();
if (typeof words[word] == "undefined")
{
words[word] = 1;
}
else
{
words[word]++;
}
}
// Sort 'em!
var wordList = [];
for (var word in words)
{
if (words.hasOwnProperty(word))
{
wordList.push([word, words[word]]);
}
}
wordList.sort(function(a, b) { return b[1] - a[1]; });
// Come back any time, straaanger!
var n = 10;
var message = ["The top " + n + " words are:"];
for (var i = 0; i < n; i++)
{
message.push(wordList[i][0] + " - " + wordList[i][1] + " occurance" +
(wordList[i][1] == 1 ? "" : "s"));
}
alert(message.join("\n"));
Reusable function:
function getTopNWords(text, n)
{
var wordRegExp = /\w+(?:'\w{1,2})?/g;
var words = {};
var matches;
while ((matches = wordRegExp.exec(text)) != null)
{
var word = matches[0].toLowerCase();
if (typeof words[word] == "undefined")
{
words[word] = 1;
}
else
{
words[word]++;
}
}
var wordList = [];
for (var word in words)
{
if (words.hasOwnProperty(word))
{
wordList.push([word, words[word]]);
}
}
wordList.sort(function(a, b) { return b[1] - a[1]; });
var topWords = [];
for (var i = 0; i < n; i++)
{
topWords.push(wordList[i][0]);
}
return topWords;
}
Once you have that array of words cleaned up, and let's say you call it wordArray:
var keywordRegistry = {};
for(var i = 0; i < wordArray.length; i++) {
if(keywordRegistry.hasOwnProperty(wordArray[i]) == false) {
keywordRegistry[wordArray[i]] = 0;
}
keywordRegistry[wordArray[i]] = keywordRegistry[wordArray[i]] + 1;
}
// now keywordRegistry will have, as properties, all of the
// words in your word array with their respective counts
// this will alert (choose something better than alert) all words and their counts
for(var keyword in keywordRegistry) {
alert("The keyword '" + keyword + "' occurred " + keywordRegistry[keyword] + " times");
}
That should give you the basics of doing this part of the work.
Try to split you string on words and count the resulting words, then sort on the counts.
This builds upon a previous answer by insin by only having one loop:
function top_words(text, n) {
// Split text on non word characters
var words = text.toLowerCase().split(/\W+/)
var positions = new Array()
var word_counts = new Array()
for (var i=0; i<words.length; i++) {
var word = words[i]
if (!word) {
continue
}
if (typeof positions[word] == 'undefined') {
positions[word] = word_counts.length
word_counts.push([word, 1])
} else {
word_counts[positions[word]][1]++
}
}
// Put most frequent words at the beginning.
word_counts.sort(function (a, b) {return b[1] - a[1]})
// Return the first n items
return word_counts.slice(0, n)
}
// Let's see if it works.
var text = "Words in here are repeated. Are repeated, repeated!"
alert(top_words(text, 3))
The result of the example is: [['repeated',3], ['are',2], ['words', 1]]
I would do exactly what you have mentioned above to isolate each word. I would then probably add each word as the index of an array with the number of occurrences as the value.
For example:
var a = new Array;
a[word] = a[word]?a[word]+1:1;
Now you know how many unique words there are (a.length) and how many occurrences of each word existed (a[word]).