hyphens in Regular Expressions/ javascript camelCase function - javascript

The Function should take a string as an argument and camel case it. I am having trouble with hyphens while using regex and string.replace() method.
camelCase('state-of-the-art') should return 'state-of-the-art'
camelCase("Don't worry kyoko") should return "dontWorryKyoko"
The following works for both cases, but I want to make it DRY, take out the hyphens if clause and include the hyphen case in .replace() and it's call-back.
function camelCase(phrase) {
let re = /[a-z]+/i;
let hyphens = /[-+]/g
if(typeof phrase !== 'string' || !phrase.match(re) || !phrase || phrase === null){
return "Please enter a valid string.";
} else if (phrase.match(hyphens)){
return phrase.toLocaleLowerCase();
}else{
return phrase.replace(/(?:^\w+|[A-Z]|\s+\w)/g, function(letter, index) {
return index == 0 ? letter.toLowerCase() : letter.toUpperCase();
}).replace(/\W+/g, '');
}
}
console.log(camelCase('state-of-the-art')) // 'state-of-the-art'
console.log(camelCase("Don't look back")) // dontLookBack
Can we make the hyphen case work without the hyphens if clause?
Also I feel like camelCase("don't lOOk_BaCK") should lowercase letters with index > 0 but it doesn't seem to be doing that in the console.
Anyone wanna help with this? Thanx

To cope with the hyphen issue you may consider - a part of alphanumeric class by using [\w-] or [^\w-] where appropriate.
To lowercase all non-first letters I suggest to match all words with (\S)(\S*) uppercasing $1 (where appropriate) and lowercasing $2:
function camelCase(phrase) {
return phrase.replace(/[^\w-]*(\S)(\S+)/g, function(_, first, rest, index) {
return (index ? first.toUpperCase() : first.toLowerCase())
+ rest.toLowerCase();
}).replace(/[^\w-]+/g, "");
}
console.log(camelCase("state-of-the-art"));
console.log(camelCase("-state-of-the-art"));
console.log(camelCase("Don't look back"));
console.log(camelCase("don't lOOk_BaCK"));
console.log(camelCase("???don't lOOk_BaCK"));

You can make the hyphens work by adding a negative lookahead assertion .replace(/(?!-)\W+/g, '');. This would tell it to replace all non-word characters, except a - dash character.
Regarding your lower-casing problem: your only criteria right now to decide the case is if it appears at the beginning of the string. Otherwise you're UPPER casing everything (including the upper case matches). This is also a pretty easy fix. Here's the whole thing:
function camelCase(phrase) {
let re = /[a-z]+/i;
if (typeof phrase !== 'string' || !phrase.match(re) || !phrase || phrase === null) {
return "Please enter a valid string.";
} else {
return phrase.replace(/(?:^\w+|(\s+)\w)|[A-Z]/g, function (letter, sp, index) {
console.log(letter, sp, index);
return (index == 0 || sp === undefined) ? letter.toLowerCase() : letter.toUpperCase();
}).replace(/(?!-)\W+/g, '');
}
}
Explanation of the changes:
change order of asssertions in phrase.replace regexp. We want a space-word combo to take precedence over a capitalized match.
add a capturing group to the space, so that we can know better if the capture follows a space
change the boolean expression: we want it to be lower case if:
it's the first character (index===0)
OR there isn't a space match (this would be an [A-Z] match, without a preceding space)
Also just as an aside, you don't appear to be camel-casing on a _ underscore character, only on spaces. Is this intentional? I've never seen a camel-case routine that didn't convert snake-case (underscore).

Related

Regular Expression Returns Undefined

I'm attempting one of the beginner coderByte challenges, Simple Symbols. Challenge summary below.
"Using the JavaScript language, have the function SimpleSymbols(str) take the str parameter being passed and determine if it is an acceptable sequence by either returning the string true or false. The str parameter will be composed of + and = symbols with several letters between them (ie. ++d+===+c++==a) and for the string to be true each letter must be surrounded by a + symbol. So the string to the left would be false. The string will not be empty and will have at least one letter."
function SimpleSymbols(str){
var RegExp = /\+\w\+/gi;
var regexp1 = /^\w/gi;
var regexp2 = /\w$/g;
if(regexp1.test(str) == true){
return false
} else if(regexp2.test(str) == true){
return false
} else if(RegExp == true){
return true
}
}
console.log(SimpleSymbols('+d+=3=+s+'));
console.log(SimpleSymbols('f++d+'));
The first regular expression I'm testing, /^\w/gi, comes back undefined, and I can't figure out why?
https://regex101.com/ is a great tool I've used before, and my expression does identify f as the first character in the string, but when I test it in codepen, it comes back undefined in the console.
Code
See regex in use here
^[+=\d]*\+(?:[a-z]\+[+=\d]*)+$
Alternatively, using the opposite logic (catching invalid strings instead of valid ones), you can use (?:^|[^+])[a-z]|[a-z](?:[^+]|$)
Usage
Please note the valid/invalid strings below have been created according to the OP's explanation of valid and invalid strings: That each letter must be surrounded by a + symbol. and that the plus sign + may be shared between characters such that +a+a+ is valid (specified in comments below the question).
var a = [
// valid
"++d+===+c++==+a++",
"+a+a+a+",
"+a++a+",
"+a+",
// invalid
"++d+===+c++==a",
"+=d+",
"+dd+",
"+d=+",
"+d+d",
"d+d+"
];
var r = /^[+=\d]*\+(?:[a-z]\+[+=\d]*)+$/mi;
a.forEach(function(s){
console.log(r.test(s));
});
Explanation
^ Assert position at the start of the line
[+=\d]* Match any number of characters in the set (+, =, or digit)
\+ Match a literal plus sign +
(?:[a-z]\+[+=\d]*)+ Match one or more of the following
[a-z] Match a lowercase ASCII letter
\+ Match a literal plus sign +
[+=\d]* Match any number of characters in the set (+, =, or digit)
$ Assert position at the end of the line
It's returning undefined because your expression does not meet any of the criteria. Since you have no else {} defined, than nothing gets returned. Thus you get undefined. Try this:
function SimpleSymbols(str){
var RegExp = /\+\w\+/gi;
var regexp1 = /^\w/gi;
var regexp2 = /\w$/g;
if(regexp1.test(str) == true){
return false
} else if(regexp2.test(str) == true){
return false
} else if(RegExp == true){
return true
} else {
return "catch all here";
}
}
console.log(SimpleSymbols('+d+=3=+s+'));
console.log(SimpleSymbols('f++d+'));
You can use a single regex and the string.test() method (which returns just true/false).
Below are 2 different ways (regex) to do it .
First requires a separate + between word chars. Example +a++b+ (true)
^
(?: [+=]* \+ \w \+ [+=]* )+
$
Second can take a common + between word chars. Example +a+b+ (true)
^
(?:
[+=]* \+ \w
(?= \+ )
)+
[+=]*
$
var patt1 = new RegExp("^(?:[+=]*\\+\\w\\+[+=]*)+$");
function SimpleSymbols_1(str){
return patt1.test(str);
}
var patt2 = new RegExp("^(?:[+=]*\\+\\w(?=\\+))+[+=]*$");
function SimpleSymbols_2(str){
return patt2.test(str);
}
console.log(SimpleSymbols_1('+d+=3=+s+'));
console.log(SimpleSymbols_1('f++d+'));
console.log(SimpleSymbols_1('+a+b+c+'));
console.log(SimpleSymbols_2('+a+b+c+'));
console.log(SimpleSymbols_2('+a+=+c+'));
console.log(SimpleSymbols_2('+a++c+'));
Thank you all for throwing some support/comments my way. Again, I am new to JavaScript and Regular Expressions are fairly foreign to me, though I am gaining some traction in understanding them. Here is the updated solution I posted. It's quite convoluted and perhaps a more inelegant and non-simple way to come to the right answer, but it worked.
function SimpleSymbols(str){
var RegExp = /\+[a-z]\+/gi;
var regexp1 = /^[a-z]/gi;
var regexp2 = /[a-z]$/g;
var regexp3 = /[a-z]\=/gi;
var regexp4 = /\=[a-z]/gi;
if(regexp1.test(str) === true){
return false
} else if(regexp2.test(str) === true){
return false
} else if(regexp3.test(str) === true){
return false
} else if(regexp4.test(str) === true){
return false
} else {
return true
}
}
console.log(SimpleSymbols('+d+=3=+s+'));
console.log(SimpleSymbols('f++d+'));
console.log(SimpleSymbols('+d===+a+'));
console.log(SimpleSymbols('+a='));
console.log(SimpleSymbols('2+a+a+'));
console.log(SimpleSymbols('==a+'));
I was sure there had to be a way to use only one regular expression, but again, I'm still very much a novice.
Thanks again everyone.

Javascript Regular Expression that diallows special characters

I have the below 3 function.
I cant seem to get the right regular expression
Please assist me
//Allow Alphanumeric,dot,dash,underscore but prevent special character and space
function Usernames(txtName) {
if (txtName.value != '' && txtName.value.match(/^[0-9a-zA-Z.-_]+$/) == null) {
txtName.value = txtName.value.replace(/[\W- ]/g, '');
}
}
//Allow Alphanumeric,dot,dash,underscore and space but prevent special characters
function Fullnames(txtName) {
if (txtName.value != '' && txtName.value.match(/^[a-zA-Z0-9. -_]+$/) == null) {
txtName.value = txtName.value.replace(/[\W-]/g, '');
}
}
//Allow Alphanumeric,dot,dash,underscore the "#" sign but prevent special character and space
function Email(txtName) {
if (txtName.value != '' && txtName.value.match(/^[a-zA-Z0-9.-_#]+$/) == null) {
txtName.value = txtName.value.replace(/[\W-]/g, '');
}
}
You don't write regular expressions to "prevent" something; they're not blacklists but whitelists. So, if someone is sending in a character that you don't want it's because your regex allowed them to. My guess as to your specific problem has to do with the .-_ part. In regex's, the X-Y means "everything from X to Y" so this would translate to "everything from . (ASCII 2E) to _ (ASCII 5F)" which ironically includes all uppercase and lowercase letters, the numbers 0 to 9, the /, the :, the ; and the # just to name a few. To avoid this, you should probably change this part to be: .\-_ as the slash will escape the dash. However, that'll still let your users make names like .Bob or -Larry and you probably don't want this so your regex should probably read:
/^[0-9a-zA-Z][0-9a-zA-Z.\-_]*$/
This will require the first character to be alphanumeric and any of the remainder to be alphanumeric, the ., the - or the _.
You'll also want to check that your value matches this reg-ex instead of not. I'm not sure what that entails in Javascript but my guess is that it's probably not value == null

How do I check for brackets in a specific place in the string?

I have this code and it needs to returns true or false based on the string you give it.
This is the only example on which it doesn't work. How can I check if brackets exist in a specific index of the string?
function telephoneCheck(str) {
var newStr = str.replace(/-/g,'').replace(/ /g,'').replace(/\(|\)/g,'');
var valid = true;
var re = /\([^()]*\)/g;
while (str.match(re))
str = str.replace(re, '');
if (str.match(/[()]/)){
valid = false;
}
if(newStr.length === 10 && valid === true && str.indexOf()){
return true;
}else if(newStr.length === 11 && str[0] != "-" && newStr[0] == 1 && valid === true){
return true;
}else{
return false;
}
}
telephoneCheck("(6505552368)");
Based on your code I think you might be looking for something like this:
'(6505552368)'.replace(/^\((\d+)\)$/, '$1');
The ^ and $ in the RegExp will match the start and the end of the string. The \d+ will match one or more numbers. The extra parentheses form a capture group that is then used in the replacement as $1.
You might be better off doing more work using RegExps rather than doing all that replacing but without knowing the exact requirements it's difficult to be more precise. I highly suggest learning more about RegExp syntax.
If you literally just want to know whether 'brackets exist in a specific index' then you can just use:
str.charAt(index) === '(';
To check if there are brackets at a specific index in the string:
/[()]/.test(str[index])
To check if there are any brackets in the string at all:
/[()]/.test(str)
If you want to test for a specific bracket type (e.g. opening but not closing) remove the other one (e.g. closing) from the regex.

Test String if each letter has '+' sign on both sides of it

this program is supposed to test str, and if every letter in str has a '+' sign on both sides of it then the function should return true. Otherwise, it should return false. I keep getting the error "SyntaxError: invalid quantifier".
function SimpleSymbols(str) {
var boolean = false;
for(var i=1;i<(str.length-1);i++){
if(/\w/.test(str.charAt(i))){
if(str.charAt(i-1).match('+') && str.charAt(i+1).match('+')){
boolean = true;
}else{
boolean = false;
}
}
}
str = boolean;
return str;
}
match is used for regular expressions, so it's trying to convert '+' to a regular expression, but it's failing because /+/ isn't a valid regular expression (it should be '\\+' or /\+/). But it's easier to just directly test each character, like this:
if(str.charAt(i-1) == '+' && str.charAt(i+1) == '+'){
Also note that /\w/ matches any 'word' character, which includes letters, numbers, and underscores. To mach just letter characters use should use /[a-z]/i (the i at the end makes it case-insensitive, so it will also match upper-case letters).
But it seems a lot simpler to invert the condition. Just test to see if the string contains any letter not surrounded by + signs or a letter at the beginning or end of the string, and return false if it does, like this:
function SimpleSymbols(str) {
return ! /(^|[^+])[a-z]|[a-z]([^+]|$)/i.test(str);
}
Much easier:
function SimpleSymbols(str) {
return !str.match(/[^+]\w/) && !str.match(/\w[^+]/);
}
The main problems with your function are:
You don't test if the first and last characters are letters. It should be safe to run your for loop from index 0 to < str.length because even though this will result in a str.charAt(-1) and str.charAt(str.length) when testing for '+' these just return "" rather than an error. Or of course you could continue with testing from the second character through to the second last in the loop and add an additional test for the first and last characters.
The .match() method does a regex match, so it tries to convert '+' to a regex and of course + has special meaning within a regex and doesn't match the literal. I'd suggest just using === '+' instead, though you could use .match(/\+/).
You are returning whatever value the boolean variable ends up with, which means your function is ignoring the tests on all but the second-last character in the string. You should return false immediately if you find a letter that doesn't have '+' around it.
Your question asked about "letters", but /\w/ doesn't test for a letter, it tests for letters or digits or underscores. If you actually want just letters use /[a-z]/i.
(Also there's no point assigning str = boolean, because JS function parameters are passed by value so this assignment won't affect anything outside the function.)
So:
function SimpleSymbols(str) {
for(var i=0;i<str.length;i++){
if(/[a-z]/i.test(str.charAt(i))){
if(str.charAt(i-1)!='+' || str.charAt(i+1) != '+'){
return false;
}
}
}
return true;
}

jQuery only allow numbers,letters and hyphens

How can I remove everything but numbers,letters and hyphens from a string with jQuery?
I found this code which allows only alphanumerical characters only but I'm not sure how I would go about adding a hyphen.
$('#text').keypress(function (e) {
var regex = new RegExp("^[a-zA-Z0-9]+$");
var str = String.fromCharCode(!e.charCode ? e.which : e.charCode);
if (regex.test(str)) {
return true;
}
e.preventDefault();
return false;
});
You just have to change the regexp to this : "^[a-zA-Z0-9\-]+$".
Note that the hyphen is escaped using \, otherwise it is used to specify a range like a-z (characters from a to z).
This code will only check if the last typed character is in the allowed list, you might also want to check if after a paste in your field, the value is still correct :
// The function you currently have
$('#text').keypress(function (e) {
var allowedChars = new RegExp("^[a-zA-Z0-9\-]+$");
var str = String.fromCharCode(!e.charCode ? e.which : e.charCode);
if (allowedChars.test(str)) {
return true;
}
e.preventDefault();
return false;
}).keyup(function() {
// the addition, which whill check the value after a keyup (triggered by Ctrl+V)
// We take the same regex as for allowedChars, but we add ^ after the first bracket : it means "all character BUT these"
var forbiddenChars = new RegExp("[^a-zA-Z0-9\-]", 'g');
if (forbiddenChars.test($(this).val())) {
$(this).val($(this).val().replace(forbiddenChars, ''));
}
});
Since there is so much attention on including a hyphen within a character class amongst these answers and since I couldn't find this information readily by Googling, I thought I'd add that the hyphen doesn't need to be escaped if it's the first character in the class specification. As a result, the following character class will work as well to specify the hyphen in addition to the other characters:
[-a-zA-Z0-9]
I think you can just put a hyphen inside the square brackets.
"^[a-z A-Z 0-9 -]+$"

Categories