Counting brackets in a string - javascript

been working on a school problem, and haven't been able to figure it out. Any help is appreciated!
Write a function named countBrackets that accepts a string
and returns the count of square bracket and curly bracket
characters in the string. That is, it should count occurrences of
these four characters “{ } [ ]”. Use function expression syntax.
var countBrackets = function(s){
let sum = 0
for(let i = ""; i == s ; i++ )
if(i ==="{}[]"){
sum+=i
}
return sum}
console.log(countBrackets("[123],{456},[{}]")) //8
console.log(countBrackets("Test string")) // 0
I'm a little confused on how I'm supposed to get it to count a string I guess.

You can use a global regex (regular expression) matching for this. The regex is between / / followed by the g flag to make it global (otherwise it only returns the first result it finds and stops).
Within the regex, | is the OR operator, so you match for /{|}|[|]/
Since [ and ] have special meaning in regular expressions you need to escape those using a \ so your total regex becomes /{|}|\[|\]/g.
This returns an array of matches, I called the function findBrackets.
To get the number of brackets, the function countBrackets just returns the .length of that array.
const findBrackets = str => str.match(/{|}|\[|\]/g);
const countBrackets = str => findBrackets(str) ? findBrackets(str).length : 0;
console.log(findBrackets('qw[e}rt[y]ui{}o{p'));
console.log(countBrackets('qw[e}rt[y]ui{}o{p'));
console.log(countBrackets('no brackets here'));
Edit: seeing the code you posted, you decided to use a for-loop to loop over your string, which is a totally valid solution.
Note that in my above example
const findBrackets = str => str.match(/{|}|\[|\]/g);
Is basically the same but a newer way of writing functions (with a few nuances)
I could have written:
var findBrackets = function(str) {
return str.match(/{|}|\[|\]/g);
}
instead which would be almost the same.
If you want to loop over a string, you can access a letter in the string by using square bracket notation, so for example
const testString = 'hello';
console.log(testString[1]);
Would output the letter 'e'.
So to use this in a function:
const countBrackets = (str) => {
let counter = 0;
for (let i = 0; i < str.length; i++) {
if (str[i] === '[' || str[i] === ']' || str[i] === '{' || str[i] === '}') {
counter++;
}
}
return counter;
}
console.log(countBrackets('qw[e}rt[y]ui{}o{p'));
Here you loop over the string from 0 to < length of the string and check every letter of it, by seeing if str[i] is {, }, [ or ], and if it is you increment a counter. After that's done you return the final count.

Related

How to use Javascript .replace() method within a for loop?

I am attempting to take a given string and replace a given number in that string with a character. Specifically:
5 is to be replaced with "S"
1 is to be replaced with "I"
0 is to be replaced with "O"
(this is a Kata exercise)
I have written a function which should:
Take the string and convert it into an array
Loop over the array
Replace each instance of the aforementioned numbers with the appropriate replacements using .replace()
Return the joined string.
My code is as appears below
Function correct(string) {
let array = string.split('')
for (let i = 0; i < array.length; i++) {
array[i].replace('5', 'S')
array[i].replace('0', 'O')
array[i].replace('1', 'I')
}
return array.join('');
}
The function returns the string exactly as initially provided, unchanged. I suspect my issue is with the way I've used the .replace() method within the loop, or the index positions declared.
String.prototype.replace returns a new string and does not mutate the variable it was executed on.
That's why you need to assign the result of replacement somewhere.
To fix your code just do the following with each replacement:
array[i] = array[i].replace('5', 'S');
Note 1: since array[i] is always a single character, there is no need in replace, because you can just compare like so:
if (array[i] === '5') {
array[i] = 'S';
}
or oneliner:
array[i] = array[i] === '5' ? 'S' : array[i];
Note 2: for loop for a replacement is not a clean code. JavaScript is very flexible and provides much better solutions to the problem. Eg. String.prototype.replaceAll.
Try this :
const inputStr = 'AB5DE0G1H';
function correct(string) {
return string.replaceAll('5', 'S').replaceAll('0', 'O').replaceAll('1', 'l')
}
console.log(correct(inputStr));
You can do with simple regex replace() based on your key=>value like this,
const key_to_replace = {
'5': 'S',
'1': 'I',
'0': 'O'
}
const correct = (str) =>
str.replace(/./g, (m) => key_to_replace[m] ?? m);
console.log(correct("this 5is a0 test1 with 55abc"))

What am I missing regarding the toUpperCase method?

I am trying to make the first letter of each word capitalized via toUpperCase method and the rest of the word is in the lower case via the toLowerCase method. But I am missing something... Why temp value is not matching with result[1][0] even if I am using that method for both?
Note: I know about other ways (map, replace, etc) for my solution, but I want to just use a for-loop with toUpperCase and toLowerCase methods.
function titleCase(str) {
let regex = /[^0-9\s]+/g;
var result = str.match(regex);
let temp = "";
for (let i = 0; i < result.length; i++) {
for (let j = 0; j < result[i].length; j++) {
result[1][0] = result[1][0].toUpperCase();
temp = result[1][0].toUpperCase();
}
}
console.log(temp); // Output is 'A'
console.log(result[1][0]); //Output is 'a'
// Normally 'temp' and 'result[1][0]' should be equal, but one returns a lowercase character and the other an uppercase character.
return str;
}
titleCase("I'm a little tea pot");
Your problem is not with the toUppercase(), it is with the reference.
When referencing result[1][0], why are you including the 0? You already have the second character with result[1]
result[1] === 'a'. No need to include the [0] as well.
Change your code so it looks like this:
function titleCase(str) {
let regex = /[^0-9\s]+/g;
var result = str.match(regex);
let temp = "";
result[1] = result[1].toUpperCase();
temp = result[1].toUpperCase();
console.log(temp); // Output is 'A'
console.log(result[1]); //Output is also 'A'
// both now equals capital A
return str;
}
titleCase("I'm a little tea pot");
EDIT:
Updating the function to uppercase the first letter of the word.
We can use ES6, which would make this really simple:
const capitalize = (string = '') => [...string].map((char, index) => index ? char : char.toUpperCase()).join('')
Use it: capitalize("hello") returns 'Hello'.
First we convert the string to an array, using the spread operator, to get each char individually as a string. Then we map each character to get the index to apply the uppercase to it. Index true means not equal 0, so (!index) is the first character. We then apply the uppercase function to it and then return the string.
If you want a more object oriented approach, we can do something like this:
String.prototype.capitalize = function(allWords) {
return (allWords) ?
this.split(' ').map(word => word.capitalize()).join(' ') :
return this.charAt(0).toUpperCase() + this.slice(1);
}
Use it: "hello, world!".capitalize(); returns "Hello, World"
We break down the phrase to words and then recursive calls until capitalising all words. If allWords is undefined, capitalise only the first word meaning the first character of the whole string.
I was tried to change a specific character in the string but strings are immutable in JS so this does not make sense.

Why non-space elements in string aren't changing to upperCase

I want to write a function to change the characters in a string at even indices to uppercase. I don't want my program to count the spaces as an even index, even if it falls on an even index.
For example: 'This is a test' => 'ThIs Is A TeSt'
I originally had this solution, but I could not get it to work to ignore the space characters when counting the even indices.
function toWeirdCase(string) {
return string.split("").map((x,i) => i%2=== 0 && x!== " " ? x.toUpperCase() : x).join("")
}
This is my second attempt and I don't know why the string elements aren't actually changing to uppercase. Any help on this would be appreciated. It is just returning the original string.
function toWeirdCase(string) {
let indexCount = 0;
let isSpace = false;
for (let i = 0; i < string.length; i++) {
if (string[i] === " ") {
isSpace = true;
}
if (indexCount % 2 === 0 && !isSpace) {
string[indexCount] = string[indexCount].toUpperCase();
}
indexCount++;
isSpace = false;
}
return string;
}
Answer:
You can use a modified reduce function that utilizes a closure as a character counter. This has the benefit of completing the transformation in one pass:
["", ...str].reduce((n =>
(r, c) => r += /\s/.test(c) ? c : c[`to${n++ & 1 ? "Lower" : "Upper"}Case`]())(0)
);
Example:
const biUpperCase = str => ["", ...str].reduce((n =>
(r, c) =>r += /\s/.test(c) ? c : c[`to${n++ & 1 ? "Lower" : "Upper"}Case`]())(0)
);
let test = biUpperCase("This is a Test");
console.log(test);
Explanation:
n is a character counter that keeps track of all non-space characters. You can think of this as an additional index that only worries about non-space characters.
We use this to determine whether or not a character is an even or odd non-space character by performing bitwise AND ( n & 1 ) or, alternatively, by performing a modulus operation ( n % 2 )
r is the accumulator in the Array.prototype.reduce method. This is what is returned by our reduce method.
Since there was no secondary parameter to Array.prototype.reduce, the first index of the Array is used as the accumulator.
This is why we perform ["", ...str] instead of simply [...str].
Syntactically we could also have written [...str].reduce( fn , "" ) instead of ["", ...str].reduce( fn ), but this would alter our succinct code.
c is the current character that we are looking at within the string array. We use RegExp.prototype.match to determine if it's a space character.
if it is we simply add the space to r ( our accumulated string )
if it is not we add a transformed character to r ( our accumulated string )
To determine which case transformation( upper or lower ) should be applied we check if n ( our character counter ) is even or odd.
if n++ & 1 is truthy the case is lower
if n++ & 1 is falsy the case is upper
Aside:
You'll notice in the snippet and code I provided that I changed your parameter name string to str. The reason for this is because String is a built-in Constructor in JavaScript and it's best to never purposefully "cross the streams" when naming variables.
In the current way that you're attempting to use this variable it makes no difference since it's properly scoped, and truthfully it is up to you if you want to take my advice. Just be aware that it could lead to an annoying, invisible problem.
Hope this Helps! Happy Coding!
You could rewind the index counter for a single word.
function toWeirdCase(string) {
return Array
.from(
string,
(i => x => (/[a-z]/i.test(x) ? i++ : (i = 0)) % 2 ? x : x.toUpperCase())
(0)
)
.join('');
}
console.log(toWeirdCase('This is a test')); // 'ThIs Is A TeSt'
A string in javascript is immutable so you will need to do something like :
let test = 'This is a test';
test = toWeirdCase(test); //Here you assign the result
And here is an example solution which ignores spaces in the count
function toWeirdCase(string) {
let count = 0;
return string.split("").map((x) => {
if(x !== " ")
count++;
if(count%2 === 0) return x.toUpperCase();
else return x;
}).join("")
}
let test = 'This is a test';
test = toWeirdCase(test);
console.log(test); //THiS iS a TeSt
Like the comments mention, strings in Javascript are immutable. That being said, you can break down the input string on whitespace, do the transformations, and join back into a string, something like this -
function toWeirdCase(sentence) {
return sentence
.split(' ')
.map(word => word
.split('')
.map((c, i) => i % 2 ? c : c.toUpperCase())
.join('')).join(' ');
}
You could store the number of spaces in a variable in the functions scope.
function toWeirdCase(string) {
let spaceCount = 0;
// Personal preference: I like the reduce fn for this, but a similar thing could be achieved with map
return string.split('').reduce((value, letter, index) => {
if (letter === ' ') spaceCount++;
return value += ((index - spaceCount) % 2)
? letter
: letter.toUpperCase();
},'')
}
This returns the leter if the index ingoring the space count has a remainder when divided by 2.
You can achieve this like so:
const str = "this is a test";
function toWeirdCase(str) {
return str.split(" ").map(word => (
[...word].map((c, i) => i % 2 ?
c.toLowerCase() :
c.toUpperCase())).join("")).join(" ");
}
console.log(toWeirdCase(str));
Updated: to set odd indexes toLowerCase() to handle edge cases like acronyms (ie: currency acronyms; "CA", "USD")
Hope this helps,

How can I find at least 1 uppercase in a string?

In es6 js I have :
good = word => {
word.split('').includes(w => w === w.toUpperCase())
}
console.log(good('Bla'))
How can I return true when finding 1 Uppercase in my string?
You can test the string using a regular expression with a character set of all uppercase letters [A-Z]:
const good = word => /[A-Z]/.test(word);
console.log(good('Bla'));
console.log(good('bla'));
Although there are much simpler ways to do this (the regex in Tushar's comment being one of them), it's possible to fix your attempt to work correctly by:
Removing the braces so that the function actually returns a value.
Using .some(), which takes a function as its argument. .includes() doesn't.
Addding const so you're actually declaring your function.
const good = word => word.split('').some(w => w === w.toUpperCase())
console.log(good('Bla'))
console.log(good('bla'))
You can do this if you want the index of it too.
function findUpperCase(str) {
return str.search(/[A-Z]/);
}
// The string which will go thorough the test
let theString = 'Hello World'
// Function to find out the answer
function stringCheck (receivedString) {
// Removing special character, number, spaces from the string to perform exact output
let stringToTest = receivedString.replace(/[^A-Z]+/ig, "")
// Variable to count: how many uppercase characters are there in that string
let j = 0
// Loop thorough each character of the string to find out if there is any uppercase available
for (i = 0; i < stringToTest.length; i++) {
// Uppercase character check
if (stringToTest.charAt(i) === stringToTest.charAt(i).toUpperCase()) {
console.log('Uppercase found: ' + stringToTest.charAt(i))
j++
}
}
console.log('Number of uppercase character: ' + j)
// Returning the output
if (j >= 1) {
return true
} else {
return false
}
}
// Calling the function
let response = stringCheck(theString)
console.log('The response: ' + response)

How to catch all upper cases in javascript

I have a string like `"TransfCoolingFanG1" I want to have the output: "TCFG1".
How I build a javascript function for this purpose?
Or, another approach (replace all EXCEPT uppercase letters and numbers):
str="TransfCo^^^oli*****ngFanG1";
str=str.replace(/[^A-Z0-9]/g,'');
console.log(str);
var str = "TransfCoolingFanG1";
var res = "";
var len = str.length;
for (var i = 0; i < len ; i++)
if (str[i] === str[i].toUpperCase())
res = res + str[i];
window.alert(res);
Maybe more native :
var yourString = "TransfCoolingFanG1";
var upString= "";
for (var i = 0; i < yourString.length;i++){
if (isUpperCase(yourString.charAt(i)));{
upString +=yourString.charAt(i);
}
}
window.alert(upString);
EcmaScript 6 approach
inputString => inputString.split('').filter(x => x === x.toUpperCase()).join('')
So what happens here in this arrow function:
Once we have inputString, we get an array of characters from it by applying function split with empty string '' separator
Once we have array of characters, we want to find all uppercase letters.
Apply filter function with an argument of predicate which tests each element of array for being uppercased or not. In case character does not equal it's uppercase variant, predicate returns false and filter erases element from array.
Last step is just collecting new string from array of filtered characters by joining it with empty string '' separator
Use String#replace method and replace all small letters.
console.log(
"TransfCoolingFanG1".replace(/[a-z]+/g, '')
)
UPDATE : If you want to remove all character except capital case or digit then use negated character class with regex.
console.log(
"TransfCoolingFanG1".replace(/[^A-Z\d]+/g, '')
)

Categories