a bit clarafication on using spread and string manipulation, foreach loop - javascript

so I've wrote this function, i want to uppercase the vowels and lowercase every other letter,
problem the end result ends with the same string, I'm new to spread and for-each,
after i spread a string does it become an array?
when i manipulate letters does it suppose to become a string again with the manipulations or do i need to join it? why aren't the upper and lowercase functions don't work?
the function:
function upperCase(str) {
var vowels = "aeiou";
[...str].forEach(letter => {
if (vowels.includes(letter)) letter.toUpperCase();
letter.toLowerCase();
});
console.log(str);
}

You have several problems:
.toUpperCase and toLowerCase return the new value, they don't mutate the existing value (and strings are immutable anyway)
Even if they did mutate the existing value, they'd change the letter string in the array and not the original string
You didn't use else to toLowerCase always runs
You need to:
return a value
Use map to collect the values
Use join() to turn the array back into a string
Such:
function upperCase(str) {
const vowels = "aeiou";
const result =
[...str]
.map(
letter =>
(vowels.includes(letter))
? letter.toUpperCase()
: letter.toLowerCase()
).join("");
console.log(result);
}
upperCase("The quick brown fox jumps over the lazy dog");

You need to assign the result of your foreach to something.
function upperCase(str) {
var vowels = "aeiou";
[...str].forEach(letter => {
if (vowels.includes(letter)) letter.toUpperCase();
letter.toLowerCase();
});
console.log(str);
}
[...str] is creating an array, looping over it, preforming an action, but then not saving the resulting array to any variable at the end. You're also missing an else and/ or a return. I think a map also makes more sense in this case.
function upperCase(str) {
var vowels = "aeiou";
const result = [...str].map(letter => {
if (vowels.includes(letter)) return letter.toUpperCase();
return letter.toLowerCase();
});
console.log(result);
}

If you just want to manipulate a string you might want to use the replace function
const newString = str.toLowerCase().replace(/[a,e,i,o,u]/g, letter => letter.toUpperCase())
This first puts everything to lower case, and afterwards replaces all vowels (matching the regular expression) by their upper case versions.

Related

string replace with return statement gives different result. need the clarity

Case 1 : replace with function return results j<*zz
const str = 'z<*zj';
const letters = Array.from(str.replace(/[^a-zA-Z]/gm, ''));
const result = str.replace(/[a-zA-Z]/gm, () => letters.pop());
console.log('result', result); // result => j<*zz/
Case 2 : replace without function return results j<*jj
const str = 'z<*zj';
const letters = Array.from(str.replace(/[^a-zA-Z]/gm, ''));
const result = str.replace(/[a-zA-Z]/gm, letters.pop());
console.log('result', result); // result => j<*jj/
So, It differs with function integration. what is behind ? Need the help to understand.
As per the documentation, If a replacement parameter is a function, it will be invoked for every match and its return value is used as the replacement text.
Hence, In case 1 as we are passing replacement as an arrow function, it executes for each match and replace with the letters array last element. As we are using Array.pop() method, It changes the length of the original array and returns the last element.
For example,
const str = 'z<*zj';
const letters = Array.from(str.replace(/[^a-zA-Z]/gm, ''));
console.log(letters.pop()); // j
console.log(letters); // ["z", "z"]
In this case, in second iteration it will pop the z and replaced with the matched value.
Now if we will talk about the case 2, As replacement parameter is a string, It will replace the substring matched by pattern in a single go.
For example,
const str = 'z<*zj';
const arr = ['z', 'z', 'j'];
const result = str.replace(/[a-zA-Z]/g, arr.pop());
console.log(result);
There exists an overload for String.prototype.replace that accepts a function. This function will execute on every match. Each match then mutates letters via the pop method.
When you use letters.pop() instead of a method that returns letters.pop(), it is only executed once and its result is reused for each match.
Since the last letter in letters is j, letters.pop() evaulates to j and each letter is replaced with j.
When using the function variant, the last letter is j, so the first letter is replaced with j, but for subsequent matches, we're now popping from a mutated array, so we then return z and finally z.

Reverse a string except for the characters contained within { } with javascript

I need to reverse a string except the characters inside of "{}". I know how to reverse a string but I'm not sure how to create the exception. Please help.
function reverseChar(string2){
let string2Array = string2.split('');
let newArray = [];
for(let x = string2Array.length-1; x >= 0; x--){
newArray.push(string2Array[x])
}
console.log(newArray)
}
reverseChar("ab{cd}efg")
reverseChar("ab{cd}ef{gh}i")
Or, maybe, this is what you want?
function reverse(str) {
return str.split("").reverse().join("").replace(/}\w+\{/g,a=>reverse(a))
}
console.log(reverse("ab{cd}efg"))
console.log(reverse("ab{cd}ef{gh}i"))
The RegExp /}\w+\{/g will find any string of characters and numbers (\w+) that is enclosed by } and {. These patterns will exist after the whole string is reverse()-d initially. In the callback function to the String.replace() method the matched string will then be reversed again.
You can try this logic:
Get all the parts
If the part does not have special character, reverse it and set it.
Reverse the parts array
Join all the parts back and return it
function reverseChar(string2) {
const regex = /(\w+(?=\{|$)|\{\w+\})/g
return string2.match(regex)
.map((str) => /\{/.test(str) ? str : str.split("").reverse().join(""))
.reverse()
.join("")
}
console.log(reverseChar("ab{cd}efg"))
console.log(reverseChar("ab{cd}ef{gh}i"))

Array manipulation error with regex - Kata 6 Codewar

In theory it should transform a given array to camel case. I don't understand what is wrong
function toCamelCase(str){
if(str.length === 0) return ""
let array = str.split(/([_-])/);
array.forEach(word =>{
word == "-" ? word.replace("") : word.charAt(0).toUpperCase()
})
return array
}
The .replace() method doesn't modify the word variable, it instead returns a new modified string. So your code is producing new values within the loop but doesn't do anything with those values. Moreover, word here is a value and not a reference to your array values, so you can't modify them directly from within your forEach() loop and expect it to modify the string values from your array. You instead need to create a new array, with each element transformed, which can be done by using .map() and returning the new value:
function toCamelCase(str) {
const array = str.split(/[_-]/);
return array.map((word, i) => {
return i === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1)
}).join("");
}
console.log(toCamelCase("this-is-some-text"));
Note that you can remove the capturing group from your .split() to remove the _ and - chars from your array so that you don't need to remove them when you map.
Note that for something like this, if you're already using regular expressions in your .split(), you might consider using .replace() with a replacement function, for example, something like:
function toCamelCase(str) {
return str.replace(/-\w/g, ([,m]) => m.toUpperCase());
}
console.log(toCamelCase("this-is-some-text"));
word == "-" ? word.replace("") : word.charAt(0).toUpperCase() is just a ternary statement floating in space. This code isn't altering any variables. It's equivalent to:
if(word == "-"){
word.replace("")
}
else{
word.charAt(0).toUpperCase()
}
Really, you don't need to mess with arrays if you make use of .replace()'s callback function.
function toCamelCase(str) {
// Match underscore or dash followed by a letter, case-insensitively
// Store the letter in a capture group; $1 in this case
return str.replace( /[_-]([a-z])/gi, function( matches ) {
// Uppercase the letter
return matches[ 1 ].toUpperCase()
} );
}
console.log( toCamelCase( 'to-be_Camel_cased' ) );

Remove all consonants in a string before a vowel then add a character

I want to remove all consonants in a string before the occurrence of a vowel and then replace it with an 'r'.
This means that 'scooby' will become 'rooby', 'xylographer' will become 'rographer' and so on. This is the algorithm I came up with:
1. Check if input type is not a string.
2. Use a variable(newStr) to hold lowercase conversion and splitted word.
3. Declare a variable(arrWord) to hold the length of the array.
4. Another variable called regex to check if a string starts with a consonant
5. Variable newArr holds the final result.
6. Search through the array, if the string does not start with a consonant
join it and return it.
7. Else keep looking for where the first vowel occurs in the word.
8. When found, remove all characters(consonants) before the vowel occurence
and replace them with an r.
9. Join the array together.
I have been able to come up with this:
const scoobyDoo = str => {
if(typeof str !== 'string'){
return 'This function accepts strings only';
}
let newStr = str.toLowerCase().split('');
let arrWord = newStr.length;
let regex = /[aeiou]/gi;
for (let i = 0; i < arrWord; i++){
if (newStr[0].match(regex)) {
let nothing = newStr.join('');
return nothing;
}
else {
let vowelIndex = newStr.indexOf(str.match(regex)[0]);
newStr.splice(0, vowelIndex, 'r');
return newStr.join('');
}
}
}
console.log(scoobyDoo('scOoby'));
I tested out the program again by capitalizing the first vowel index and instead of 'rooby' I get 'rscooby'. Why is that so?
Can you once try with following code in your else and see the changes
else {
var vowelIndex = newStr.indexOf(str.match(regex)[0]);
newStr.splice(0, vowelIndex, 'r');
return newStr.join("");
}
Is it not much easier like this? Or am I missing something??
'xylographer'.replace(/^\s*[^aieou]+(?=\w)/i,function(m,o,s){return "r"})
//"rographer"
'scooby'.replace(/^\s*[^aieou]+(?=\w)/i,function(m,o,s){return "r"})
//"rooby"
you could just use one reg expression for the whole algorithm and no need to split your string no more.
regexp to use.
/^[^aouie, AOUIE]+(?=[aouie, AOUIE])/g
of course you can readjust regexp to suit you more but this will get your main requirement.
On the line immediately after the else statement, I just called .toLowerCase() on it and it was fixed:
let vowelIndex = newStr.indexOf(str.match(regex)[0].toLowerCase());
I like keeping my code simple and readable
function pattern(str){
var vowelIndex = str.indexOf(str.match(/[aeiou]/)); //returns index of first vowel in str
return "r" + str.slice(vowelIndex);
}
console.log(pattern('xylographer'));

Why doesn't it recognize join() as a function?

I'm trying to capitalize every first letter of the given string, however every time I run the code I get the following error:
TypeError: val[i].charAt(...).toUpperCase(...).join is not a function
function titleCase(str) {
var strArry = str.toLowerCase().split(' ');
strArry.map(function (val) {
for (var i = 0; i < val.length; i++) {
return val[i].charAt(0).toUpperCase().join(' ') + strArry[i].splice(1);
};
});
}
titleCase("I'm a little tea pot");
String.protoype.toUpperCase() returns a string, and Array.prototype.join() is on the Array prototype, not the string.
You probably want something like this...
return val[i].charAt(0).toUpperCase() + val[i].slice(1);
...or possibly even better (at least shorter)...
function titleCase(str) {
return str.replace(/\b[a-z]/g, function(match) { return match.toUpperCase(); });
}
Here I am using a regex to match the first lowercase letter after a word boundary, and then using a custom replacer to return it uppercased.
If you supported more than latin, then use a Unicode range to select the characters.
toUpperCase returns a String and join is not a method on that prototype.
If you run through your code and put a typeof check in before mucking with the string, you can see:
function titleCase(str) {
var strArry = str.toLowerCase().split(' ');
strArry.map(function (val) {
for (var i = 0; i < val.length; i++) {
var temp = val[i].charAt(0).toUpperCase();
console.log(typeof temp);
return temp;
};
});
}
titleCase("I'm a little tea pot");
You need to join the Array after you've mapped it to produce the final combined value.
I propose this short piece of code which works well :
var titleCase = (str) => str.split(" ").map(el => el[0].toUpperCase().concat(el.substr(1))).join(" ");
console.log(titleCase("I'm a little tea pot"));
Figured it out with a bit a research and found that using val worked with me trying to use mpa()
function titleCase(str) {
var strArry = str.toLowerCase().split(' ');
var convert = strArry.map(function(val) {
return val.replace(val.charAt(0), val.charAt(0).toUpperCase());
});
return convert.join(' ');
}
titleCase("I'm a little tea pot");
Im am not Familiar with Javascript, which is why I fo not know if it makes a difference between char and string.
I am quite sure you meant do an entirely different thing, namely return a string joined from capitalized letters. What you are (trying) to do here however is returning the result of your expression (val[i].andsoonandsoforth) after the first cycle of your for loop.
The reason why the expression doesn't work will be that join(string) is usually called on arrays of strings or characters. You are calling it on a single character however!
The solution would be to first split uf the string into characters, capitalize them, store them into an array, call join on that array and return the thing afterwards.
Or just use the likely existent builtin capitalize functions on strings.

Categories

Resources