This question already has answers here:
Counting the vowels in a string using Regular Expression
(2 answers)
Closed 1 year ago.
I tried to write a function which checks if a given string contains vowels and I cannot see why it works for some words 'cat' and 'why' but not 'DOG', i believe that i have accounted for uppercase.
const containsVowels = string => {
var lowerCase = string.toLowerCase();
var word = lowerCase.split("");
var vowelsArray = ["a","o","i","u","y"];
const result = word.filter(letter => vowelsArray.includes(letter));
return result.includes("a","o","i","u","y");
};
includes takes only 2 parameters, the first one being searchElement and second parameter being fromIndex.
Reference : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#parameters
You wouldn't want to do the last check if the result array contains vowels or not, because in the previous step itself you are filtering out the word to get array that contains only vowels. So just check if the array is empty or it contains any elements inside it.
const containsVowels = str => {
let lowerCase = str.toLowerCase();
let word = lowerCase.split("");
let vowelsArray = ["a","o","i","u","y"];
const result = word.filter(letter => vowelsArray.includes(letter));
return result.length > 0;
};
console.log(containsVowels("cat"));
console.log(containsVowels("DOG"));
console.log(containsVowels("BCDF"));
Suggestion: Don't use built in keywords as variables.
As pointed out by Muhammad, we can regex to find if the string contains vowels
const containsVowel = str => {
const vowelRegex = /[aeiou]/i;
return vowelRegex.test(str);
};
2 Problems,
Why would you use includes twice ?
&
You cannot use includes like
result.includes("a","o","i","u","y");
includes only accepts 2 param:
includes(searchElement, fromIndex)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
By filtering, you already know the result.
What you should do is, compare the length of the result:
const containsVowels = string => {
let lowerCase = string.toLowerCase();
let word = lowerCase.split("");
let vowelsArray = ["a","o","i","u","y"];
const result = word.filter(letter => vowelsArray.includes(letter));
return result.length > 0 ? true : false
};
use regex to get the result.
var regEx = /[aeiou]/gi
var test_string = "Cat";
var match = test_string.match(regEx)
if(match)
console.log("Match found", match)
when you write something like this
result.includes("a","o","i","u","y")
this compare with only it's first element which is "a" and one thing you don't need to write the above mentioned code further.
After filtering just replace the above code with
return result.length > 0 ? true : false
Related
I was taking on a JS challenge to take a first/last name string input and do the following:
swap the first letter of first/last name
convert all characters to lowercase, except for the first characters, which need to be uppercase
Example:
input: DonAlD tRuMp
output: Tonald Drump
The following is the code I came up with:
const input = prompt("Enter a name:")
function switchFirstLetters(input) {
let stringArray = input.split('');
for(let i=0; i < stringArray.length; i++) {
if(stringArray[i - 1] === ' ') {
[stringArray[0], stringArray[i]] = [stringArray[i], stringArray[0]]; // destructuring
}
}
return result = stringArray.join('');
}
let swappedString = switchFirstLetters(input);
function capFirstLetters(swappedString) {
let stringArray = swappedString.toLowerCase();
stringArray = stringArray.split('');
stringArray[0] = stringArray[0].toUpperCase();
for(let i=0; i < stringArray.length; i++) {
if(stringArray[i - 1] === ' ') {
stringArray[i] = stringArray[i].toUpperCase();
}
}
return result = stringArray.join('');
}
let finalString = capFirstLetters(swappedString);
console.log(finalString);
My thought process for the switchFirstLetters function was:
Create an array from the string parameter
Run through the array length. If the value of the element prior the current element is equal to ' ', use destructuring to swap the current element with the element at index 0
Concatenate elements into a new string and return that value
My thought process for the capFirstLetters function:
Convert all characters in the string to lowercase (this could be handled outside of the function as well)
Create an array from the new, lowercase string
Make character at index 0 be uppercase (this could also be integrated into the for loop)
Run through the array length. If the value of the element prior to the current element is equal to ' ', convert that element to uppercase.
Concatenate array elements into a new string
The code works, but I'm still early in my coding journey and realize it's likely not an ideal solution, so I was wondering if anyone here could help me optimize this further to help me learn. Thanks!
You could also use a regular expression to replace the first letters:
let name = "DonAlD tRuMp";
let result = name.toLowerCase().replace(/(\S)(\S*\s+)(\S)/g, (_, a, b, c) =>
c.toUpperCase() + b + a.toUpperCase()
);
console.log(result);
The regular expression uses \S (a non-white-space character), \S* (zero or more of those), \s+ (one or more white-space characters) and parentheses to create capture groups. These three groups map to a,b,c parameters in the callback function that is passed to replace as second argument. With these parts the replacement string can be constructed. Both the capitalisation and the switch happen in the construction.
If the replace function is a little overwhelming, my attempt introduces the for-of loop, the substring string method, array slice as well as the && short circuit evaluation. You should also be aware you can access a given character of a string using the square bracket syntax, just like array, but string has it's own set of methods which tend to have different names.
Definitely take a look at the replace function, to make your v2.
const rawNameInput = "DonAlD jUnior tRuMp"
const nameInput = rawNameInput.trim()
const rawNameWords = nameInput.split(" ")
const nameWords = []
for (const word of rawNameWords) {
const first = word[0].toUpperCase()
const rest = word.substring(1).toLowerCase()
nameWords.push(first + rest)
}
const middleNames = nameWords.slice(1, -1).join(" ")
const lastIdx = nameWords.length - 1
const newFirstName = nameWords[lastIdx][0] + nameWords[0].substring(1)
const newLastName = nameWords[0][0] + nameWords[lastIdx].substring(1)
console.log(`${newFirstName} ${middleNames && middleNames + " "}${newLastName}`)
I want to know about the algorithm for below question in JavaScript.
Check whether the given word can be "programming" or not by removing the substring between them. You can only remove one substring from the given the word.
Give answer in 'yes' and 'no'
example answer explanation
"progabcramming" yes remove substring 'abc'
"programmmeding" yes remove substring 'med'
"proasdgrammiedg" no u have to remove 2 subtring 'asd' and 'ied'
which is not allowed
"pxrogramming" yes remove substring 'x'
"pxrogramminyg" no u have to remove 2 subtring 'x' and 'y'
which is not allowed
Please tell me an algorithm to solve it
{
// will create a regexp for fuzzy search
const factory = (str) => new RegExp(str.split('').join('(.*?)'), 'i')
const re = factory('test') // re = /t(.*?)e(.*?)s(.*?)t/i
const matches = re.exec('te-abc-st') ?? [] // an array of captured groups
const result = matches
.slice(1) // first element is a full match, we don't need it
.filter(group => group.length) // we're also not interested in empty matches
// now result contains a list of captured groups
// in this particular example a single '-abc-'
}
I'm not sure how efficient this code is, but only thing i can come up with is using regular expression.
const word = 'programming';
const test = ['progabcramming', 'programmmeding', 'proasdgrammiedg', 'pxrogramming', 'pxrogramminyg', 'programming'];
// create regular expression manually
// const regexp = /^(p).+(rogramming)|(pr).+(ogramming)|(pro).+(gramming)|(prog).+(ramming)|(progr).+(amming)|(progra).+(mming)|(program).+(ming)|(programm).+(ing)|(programmi).+(ng)|(programmin).+(g)$/;
// create regular expression programmatically
let text = '/^';
word.split('').forEach((character, i) => {
text += i ? `(${word.substring(0, i)}).+(${word.substring(i)})|` : '';
});
text = text.substring(text.length - 1, 1) + '$/';
const regexp = new RegExp(text);
// content output
let content = '';
test.forEach(element => {
content += `${element}: ${regexp.test(element)}\n`;
});
document.body.innerText = content;
Following up from this thread, im trying to make this work
JavaScript regular expression to match X digits only
string = '2016-2022'
re = /\d{4}/g
result = [...string.matchAll(re)]
This returns an array of two arrays. Is there a way to consolidate this into 1 array?
However it doesn't look like this is returning the desired results
I'm new to regular expression. What am I doing wrong?
this return an array of matches
result = string.match(re)
This is a function to parse the string encoding those two year values and return the inner years as items of an array:
let o = parseYearsInterval('2016-2022');
console.log(o);
function parseYearsInterval(encodedValue){
var myregexp = /(\d{4})-(\d{4})/;
var match = myregexp.exec(encodedValue);
if (match != null) {
let d1 = match[1];
let d2 = match[2];
//return `[${d1}, ${d2}]`;
let result = [];
result.push(d1);
result.push(d2);
return result;
} else {
return "not valid input";
}
}
I think there are better ways to do that like splitting the string against the "-" separator and return that value as is like:
console.log ( "2016-2022".split('-') )
Just do a split if you know that only years are in the string and the strucutre isn't changing:
let arr = str.split("-");
Question
string = '2016-2022'
re = /\d{4}/g
result = [...string.matchAll(re)]
This returns an array of two arrays. Is there a way to consolidate
this into 1 array?
Solution
You may simply flat the result of matchAll.
let string = '2016-2022'
let re = /\d{4}/g
console.log([...string.matchAll(re)].flat())
Alternative
If your structure is given like "yyyy-yyyy-yyyy" you might consider a simple split
console.log('2016-2022'.split('-'))
var str = '2016-2022';
var result = [];
str.replace(/\d{4}/g, function(match, i, original) {
result.push(match);
return '';
});
console.log(result);
I also wanted to mention, that matchAll does basicly nothing else then an while exec, that's why you get 2 arrays, you can do it by yourself in a while loop and just save back what you need
var result = [];
var matches;
var regexp = /\d{4}/g;
while (matches = regexp.exec('2016-2022')) result.push(matches[0]);
console.log(result);
I need to get the last uppercase letter from the string and wondering how can I do it. I want to write a function that takes the string and returns the last uppercase letter from that string.
For example, If I call the function with word 'LonDon', I should get D. And if I call the function with word 'CaliforNia', I get N.
Thank you so much for your time.
function findLastCap(text) {
let length = text.length - 1;
for (let i = length; i >= 0; i--) {
if (text[i] !== text[i].toLowerCase()) return text[i];
}
return false;
}
console.log(findLastCap("aaaaaaBccc"))
Use a Regular Expression, probably [A-Z](?=[^A-Z]*$)
[A-Z]: match any capital letter
(?=[^A-Z]*$): Followed by any # of non-uppercase and the end of the string.
let regex = /[A-Z](?=[^A-Z]*$)/;
console.log({
CaliforNia: 'CaliforNia'.match(regex)[0],
LonDon: 'LonDon'.match(regex)[0]
});
I do not know javascript but I can help you come up with an algorithm that would solve this problem.
First I will write it in python3 and explain what I did and you can try to translate it into javascript.
def last_upper(string):
last = "" # i make a string var here
for let in string:
if let.issupper():
last = let
return last
So basically what I did in this code is that I iterate through all the elements in the string and if a letter is uppercase it will update the last variable. It works because it keeps on updating it each time it finds a uppercase letter.
Try this,
let reg = /[A-Z](?=[^A-Z]*$)/g
let p = "Parts spaR";
p.match(reg)
Or you can get all the matches and access the last one,
let reg = /[A-Z]/g
let r = p.match(reg)
let found = r[r.length-1]
let tempString=`aaaaaBcCcF`;
let result = tempString.split('').filter(value => {
let str = '';
if (value === value.toUpperCase()) {
str = value;
}
return str;
})
console.log(result[result.length-1]);
I have a string like this,
var str = " This is a ?sample? text to ?extract? question marks separated texts into an array in ?Javascript?. "
I want a javascript array as below,
arr = {
'sample',
'extract',
'Javascript'
}
You can alternate between keeping and ignoring letters each time you get to a "?". This will not include the text after an opening ? if there is no closing ?.
let str = "This ?? should ?only? leave ?four words? ?in? the ?result?. Ignoring if there is no ? closing question mark"
let result = []
let openingQuestionMark = false
let substring = ""
for (let key of str) {
if (key === "?") {
if (openingQuestionMark) {
substring && result.push(substring)
substring = ""
}
openingQuestionMark = !openingQuestionMark
continue
}
if (openingQuestionMark) {
substring += key
}
}
console.log(result)
You can split() and then filter() the results having an odd index :
// After the split('?'), an array will be created. One needs the odd indexes
// 0 1 2 3 4 5 6 7
const str = " This is a ?sample? text to ?extract? question marks separated texts into an array in ?Javascript?. ?";
const arr = str.split('?').filter((word, index) => index % 2 !== 0 && word !== '');
console.log(arr);
This will be working only if you are sure that the input contains only an even number of ?. An input like "foo?bar" will output [ 'bar' ].
To make sure this work with any input, you can use RegEx :
function getWordsBetweenParenthesis(input)
{
const pattern = /(?:\?)(.*?)(?:\?)/gm;
const matches = input.matchAll(pattern);
return [...matches].map(arr => arr[1]);
}
console.log(getWordsBetweenParenthesis(" This is a ?sample? text to ?extract? question marks separated texts into an array in ?Javascript?. "));
console.log(getWordsBetweenParenthesis("foo?bar"));
console.log(getWordsBetweenParenthesis("foo??bar"));
console.log(getWordsBetweenParenthesis("?hello?World?"));
console.log(getWordsBetweenParenthesis("?hello??World?"));