Alternate capitalisation in a string - javascript

I would like to create a function which alternates letter capitalisation. For example, Hello World would become HeLlO wOrLd. The first letter of the string must always be capitalised.
Here is the code I have written:
function alternatingCaps(str) {
let alternate = str.charAt(0).toUpperCase();
for(let i = 1; i < str.length; i++) {
let previousChar = str.charAt(i - 1);
if(previousChar === previousChar.toUpperCase())
alternate += str.charAt(i).toLowerCase();
else if(previousChar === previousChar.toLowerCase())
alternate += str.charAt(i).toUpperCase();
}
return alternate;
}
I declared the alternate variable with the capitalised first character of the supplied string. I then loop through the rest of the string and check if the character preceding the current iteration is uppercase or lowercase; whichever it is, the current letter will become the opposite.
However, this does not have the desired outcome. Here are a couple of tests and their corresponding results:
console.log(alternatingCaps('hello world'));
// Output: "HELLO wORLD"
console.log(alternatingCaps('jAvaScrIPT ruLEZ'));
// Output: "JAvAScRIpt rULez"
How do I fix my function?

let s = 'hello there this is a test';
s = s.split('').map( (letter,i) => (i % 2) == 0 ? letter.toUpperCase() : letter.toLowerCase() ).join('')
console.log( s );
Update: if you want to ignore but preserve the spaces, then here is another solution, albeit a little screwy. It doesn't just ignore spaces, it only operates on letters matching the regular expression.
let s = 'hello there this is a test';
let ul = false;
s = s.split('').map(letter => letter.match(/[a-zA-Z]/) != null ? (ul = ! ul, ul ? letter.toUpperCase() : letter.toLowerCase()) : letter).join('');
console.log( s );

Simplest solution i can think of is using for loop and Remainder operator.
let alterNate = (input) => {
let str = ''
let last = 'L'
for(let i=0; i<input.length; i++){
if( /[a-z]/ig.test(input[i]) ) {
if(last==='L'){
str+= input[i].toUpperCase()
last = 'U'
} else{
str+= input[i].toLowerCase()
last = 'L'
}
} else {
str+=input[i]
}
}
return str;
}
console.log(alterNate('hello world'))

My solution uses RegEx replace to achieve the expected result:
function alternatingCaps(str) {
return str.replace(/\w(.|$)/g, s => s[0].toUpperCase() + (s[1] ? s[1].toLowerCase() : ''));
}
console.log(alternatingCaps('hello world'));
console.log(alternatingCaps('jAvaScrIPT ruLEZ'));
There are two things to pay attention for:
\w(.|$) - This regular expression captures a word character (\w) and any other following char. The (.|$) address for an odd number of characters. We're basically capturing the characters in pairs here;
s => s[0].toUpperCase() + (s[1] ? s[1].toLowerCase() : '') - This replacing function does the rest of the job:
s[0].toUpperCase() - It takes s[0] and changes it to uppercase;
(s[1] ? s[1].toLowerCase() : '') - And it takes s[1], if it exists, and changes it to lowercase.

Here is the sample regex for alternating case
[A-Z]([a-z][A-Z])*[a-z]?
https://regex101.com/r/UPHRUk/1

Related

UpperCase the even index of a string

i am trying to UpperCase() the even indexes of a string;
input: hello world;
output: HeLlO WoRlD;
somehow its not working, i think it is because i cannot mutate a string since it is returning the initial value. Can someone help me solve this problem ?
/* Alternating Caps
Write a function that takes in a string of letters
and returns a sentence in which every other letter is capitalized.
Example input: "I'm so happy it's Monday"
Example output: "I'M So hApPy iT'S MoNdAy"
*/
function altCaps(str){
let string = str
for(let i = 0; i < str.length; i++) {
if(i % 2 === 0) {
string[i].toUpperCase()
}
}
console.log(string)
}
Strings are immutable, you need to create a new string and append the letters one by one.
function altCaps(oldStr){
let newStr = '';
for(let i = 0; i < oldStr.length; i++)
newStr += i % 2 === 0 ? oldStr[i].toUpperCase() : oldStr[i];
return newStr;
}
console.log(altCaps("I'm so happy it's monday"))
Notice this isn't attempting to mutate newStr, it's getting a new string reassigned for every letter we append.
function altCaps(text,mode=0) {
return text.split('').map((c,i) =>
i % 2 == mode ? c.toLowerCase() : c.toUpperCase()
).join('');
}
console.log(altCaps("I'm so happy it's Monday",1));
The problem with your solution is that .toUpperCase() doesn't modify the string it's called on. Rather, it returns a new upper-cased string.
Here's one way the problem could be solved:
const test = "Hello World";
const toAltCase = s => s.split("")
.map((c, i) => (i % 2 != 0)?
c.toLowerCase() :
c.toUpperCase())
.join("");
console.log(toAltCase(test), "<-", test);

I was wondering if there is any other solution to this problem. JAVASCRIPT

Given a string, return a new string where the first and last chars have been exchanged.
Examples
frontBack('code') → eodc
frontBack('a') → a
frontBack('ab') → ba
//Code
function frontBack(str){
let first = str.charAt(0);
let last = str.charAt(str.length-1);
let newStr = str.slice(1, str.length-1);
if (str.length == 1) {`enter code here`
return str;
}
else {
return last + newStr + first;
}
}
You could use a regular expression and capture the first and last character, then replace them with each other. Thanks to #Ivar for pointing out a simplification:
const frontBack = str => str.replace(
/(.)(.*)(.)$/g, '$3$2$1'
);
console.log(
frontBack('code'),
frontBack('a'),
frontBack('ab')
);
If there's only one character in the input, it won't get matched, so it'll be returned unchanged.
If there are two or more characters in the input, the first character will be captured, and the middle capture group will expand only as needed so that the final capture group and its one character touches the end of the string.
You could also turn it into an array and replace both ends at the same time:
const frontBack = str => {
const arr = [...str];
[arr[0], arr[arr.length - 1]] = [arr[arr.length - 1], arr[0]];
return arr.join('');
};
console.log(
frontBack('code'),
frontBack('a'),
frontBack('ab')
);
But your current code is a fine solution too.
const frontBack = (str = '') => `${str.charAt(0)}${str.slice(1, str.length - 1)}${str.charAt(str.length - 1)}`;
For example.

Finding the index to a non-specified character

Let's say for example I have a string
thisIsThisTuesday Day
I want to find the index of all the capital letters, test if there is a space before it, and if not insert one. I would need the index of each one.
At least from what I can see indexOf(String) will only produce the index of the first occurance of the character T/t
This :
for(i=0;i<str.length;i++){
let char=str[i];
if(isNaN(char*1)&&char==char.toUpperCase()){
y=str.indexOf(char);
console.log(char,y)
}
}
would produce the capital letters, and their indexes but will only display the first occurrence of the character in question. I feel pretty confident that the part I am missing is a for() loop in order to move the index iteration..but it escapes me.
Thank you in advance!
You can use a regex:
It matches any non-whitespace character followed by a capital letter and replaces it by the two characters with a space between.
const str = "thisIsThisTuesday Day";
const newstr = str.replace(/([^ ])([A-Z])/g, "$1 $2");
console.log(newstr);
You can use the following regular expression:
/(?<=\S)(?=[A-Z])/g
The replace will insert spaced between characters which are non-space followed by a capital letter.
See example below:
let str = "thisIsThisTuesday Day";
const res = str.replace(/(?<=\S)(?=[A-Z])/g, ' ');
console.log(res);
Note: As pointed out ?<= (positive lookbehind) is currently not be available in all browsers.
Actually, the String.indexOf function can take a second argument, specifying the character it should start searching from. Take a look at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
But, if you just want to find all capital letters and prefix them with a space character, if one is not found, there are many approaches, for example:
var str = "thisIsThisTuesday Day";
var ret = '';
for (var i=0; i<str.length; i++) {
if (str.substr(i, 1) == str.substr(i, 1).toUpperCase()) {
if ((i > 0) && (str.substr(i - 1,1) != " "))
ret += " ";
}
ret += str.substr(i,1);
}
After running this, ret will hold the value "this Is This Tuesday Day"
You could iterate over the string and check if each character is a capital. Something like this:
const s = 'thisIsThisTuesday Day';
const format = (s) => {
let string = '';
for (let c of s) {
if (c.match(/[A-Z]/)) string += ' ';
string += c;
}
return string;
};
console.log(format(s));
Or alternatively with reduce function:
const s = 'thisIsThisTuesday Day';
const format = (s) => s.split('').reduce((acc, c) => c.match(/[A-Z]/) ? acc + ` ${c}` : acc + c, '');
console.log(format(s));

Adding a whitespace in front of the first number in a string

I need a whitespace to be added in front of the first number of a string, unless there is one already and unless the number is the first character in the string.
So I wrote this JS code:
document.getElementById('billing:street1').addEventListener('blur', function() {
var value = document.getElementById('billing:street1').value;
var array = value.match(/\d{1,}/g);
if (array !== null) {
var number = array[0];
var index = value.indexOf(number);
if(index !== 0){
var street = value.substring(0, index);
var housenumber = value.substring(index);
if (street[street.length - 1] !== ' ') {
document.getElementById('billing:street1').value = street + ' ' + housenumber;
}
}
}
});
Fiddle
It works fine, but I feel like this can probably be done in a smarter, more compact way.
Also, JQuery suggestions welcome, I am just not very familiar with it.
Try this one :
const addSpace = (str) => {
return str.replace(/(\D)(\d)/, "$1 $2")
}
console.log(addSpace("12345")) // "12345"
console.log(addSpace("city12345")) // "city 12345"
console.log(addSpace("city")) // "city"
(\D) captures a non-digit
(\d) captures a digit
so (\D)(\d) means : non-digit followed by a digit
that we replace with "$1 $2" = captured1 + space + captured2
You can do it by using only regular expressions. For example:
var s = "abcde45";
if(!s.match(/\s\d/)){
s = s.replace(/(\d)/, ' $1');
}
console.log(s); // "abcde 45"
UPD : Of course, if you have string with a wrong syntax(e.g no numbers inside), that code wouldn't work.

Swap Case on javascript

I made a script that changes the case, but result from using it on text is exactly the same text, without a single change. Can someone explain this?
var swapCase = function(letters){
for(var i = 0; i<letters.length; i++){
if(letters[i] === letters[i].toLowerCase()){
letters[i] = letters[i].toUpperCase();
}else {
letters[i] = letters[i].toLowerCase();
}
}
console.log(letters);
}
var text = 'So, today we have REALLY good day';
swapCase(text);
Like Ian said, you need to build a new string.
var swapCase = function(letters){
var newLetters = "";
for(var i = 0; i<letters.length; i++){
if(letters[i] === letters[i].toLowerCase()){
newLetters += letters[i].toUpperCase();
}else {
newLetters += letters[i].toLowerCase();
}
}
console.log(newLetters);
return newLetters;
}
var text = 'So, today we have REALLY good day';
var swappedText = swapCase(text); // "sO, TODAY WE HAVE really GOOD DAY"
You can use this simple solution.
var text = 'So, today we have REALLY good day';
var ans = text.split('').map(function(c){
return c === c.toUpperCase()
? c.toLowerCase()
: c.toUpperCase()
}).join('')
console.log(ans)
Using ES6
var text = 'So, today we have REALLY good day';
var ans = text.split('')
.map((c) =>
c === c.toUpperCase()
? c.toLowerCase()
: c.toUpperCase()
).join('')
console.log(ans)
guys! Get a little simplier code:
string.replace(/\w{1}/g, function(val){
return val === val.toLowerCase() ? val.toUpperCase() : val.toLowerCase();
});
Here is an alternative approach that uses bitwise XOR operator ^.
I feel this is more elegant than using toUppserCase/ toLowerCase methods
"So, today we have REALLY good day"
.split("")
.map((x) => /[A-z]/.test(x) ? String.fromCharCode(x.charCodeAt(0) ^ 32) : x)
.join("")
Explanation
So we first split array and then use map function to perform mutations on each char, we then join the array back together.
Inside the map function a RegEx tests if the value is an alphabet character: /[A-z]/.test(x) if it is then we use XOR operator ^ to shift bits. This is what inverts the casing of character. charCodeAt convert char to UTF-16 code. XOR (^) operator flips the char. String.fromCharCode converts code back to char.
If RegEx gives false (not an ABC char) then the ternary operator will return character as is.
References:
String.fromCharCode
charCodeAt
Bitwise operators
Ternary operator
Map function
One liner for short mode code wars:
let str = "hELLO wORLD"
str.split("").map(l=>l==l.toLowerCase()?l.toUpperCase():l.toLowerCase()).join("")
const swapCase = (myString) => {
let newString = ''; // Create new empty string
if (myString.match(/[a-zA-Z]/)) { // ensure the parameter actually has letters, using match() method and passing regular expression.
for (let x of myString) {
x == x.toLowerCase() ? x = x.toUpperCase() : x = x.toLowerCase();
newString += x; // add on each conversion to the new string
}
} else {
return 'String is empty, or there are no letters to swap.' // In case parameter contains no letters
}
return newString; // output new string
}
// Test the function.
console.log(swapCase('Work Today Was Fun')); // Output: wORK tODAY wAS fUN
console.log(swapCase('87837874---ABCxyz')); // Output: 87837874---abcXYZ
console.log(swapCase('')); // Output: String is empty, or there are no letters to swap.
console.log(swapCase('12345')); // Output: String is empty, or there are no letters to swap.
// This one will fail. But, you can wrap it with if(typeof myString != 'number') to prevent match() method from running and prevent errors.
// console.log(swapCase(12345));
This is a solution that uses regular expressions. It matches each word-char globally, and then performs a function on that matched group.
function swapCase(letters) {
return letters.replace( /\w/g, function(c) {
if (c === c.toLowerCase()) {
return c.toUpperCase();
} else {
return c.toLowerCase();
}
});
}
#this is a program to convert uppercase to lowercase and vise versa and returns the string.
function main(input) {
var i=0;
var string ='';
var arr= [];
while(i<input.length){
string = input.charAt(i);
if(string == string.toUpperCase()){
string = string.toLowerCase();
arr += string;
}else {
string = string.toUpperCase();
arr += string;
}
i++;
}
console.log(arr);
}
Split the string and use the map function to swap the case of letters.
We'll get the array from #1.
Join the array using join function.
`
let str = 'The Quick Brown Fox Jump Over A Crazy Dog'
let swapedStrArray = str.split('').map(a => {
return a === a.toUpperCase() ? a.toLowerCase() : a.toUpperCase()
})
//join the swapedStrArray
swapedStrArray.join('')
console.log('swapedStrArray', swapedStrArray.join(''))
`
A new solution using map
let swappingCases = "So, today we have REALLY good day";
let swapping = swappingCases.split("").map(function(ele){
return ele === ele.toUpperCase()? ele.toLowerCase() : ele.toUpperCase();
}).join("");
console.log(swapping);
As a side note in addition to what has already been said, your original code could work with just some minor modifications: convert the string to an array of 1-character substrings (using split), process this array and convert it back to a string when you're done (using join).
NB: the idea here is to highlight the difference between accessing a character in a string (which can't be modified) and processing an array of substrings (which can be modified). Performance-wise, Fabricator's solution is probably better.
var swapCase = function(str){
var letters = str.split("");
for(var i = 0; i<letters.length; i++){
if(letters[i] === letters[i].toLowerCase()){
letters[i] = letters[i].toUpperCase();
}else {
letters[i] = letters[i].toLowerCase();
}
}
str = letters.join("");
console.log(str);
}
var text = 'So, today we have REALLY good day';
swapCase(text);

Categories

Resources