I am trying to select words being passed through an IF statement based on only their character length, ignoring symbols.
For example If I have the word "hello!" I want the if statement to recognise it as a length of 5 characters.
I want to keep the symbol in the word when it is then added to updatedString. I just don't want to count the symbol in the original count. I have spent a while considering regex options but am struggling to find something that would work in this particular case.
An example of part of the code is below. (updatedString is declared outside of the if-loop)
for (let word in arr) {
if (arr[word].length == 5 || arr[word].length == 6) {
let bold = arr[word].slice(0, 3)
let normal = arr[word].slice(3)
updatedString += `<b>${bold}</b>${normal} `
}
else if {
...
}
}
What I ultimately want is the area "arr[word].length == 5" to only count characters.
For the sake of this program I will assume that all words input in via the user will be those used in normal news or academic articles and nothing too obscure.
Any advice would be greatly appreciated, thanks.
You can use regex like so:
text = "hello!"
text.match(/[a-z]/g).join("") // join to return a string without any symbols
If you need to match more characters just update the pattern.
In your particular case it would look something like this:
for (let word in arr) {
if (arr[word].match(/[a-z]/g).length == 5 || arr[word].match(/[a-z]/g).length == 6) {
let bold = arr[word].slice(0, 3)
let normal = arr[word].slice(3)
updatedString += `<b>${bold}</b>${normal} `
}else if (/* [...] */) {
// [...]
}
}
I was solving the Coderbyte Challenge - Questions Marks
When I run my code in the browser it all works fine, however, once I run it on the coderbyte website it throws an error.
The Challenge is:
Have the function QuestionsMarks(str) take the str string parameter,
which will contain single digit numbers, letters, and question marks,
and check if there are exactly 3 question marks between every pair of
two numbers that add up to 10. If so, then your program should return
the string true, otherwise it should return the string false. If there
aren't any two numbers that add up to 10 in the string, then your
program should return false as well.
For example: if str is "arrb6???4xxbl5???eee5" then your program
should return true because there are exactly 3 question marks between
6 and 4, and 3 question marks between 5 and 5 at the end of the
string.
Use the Parameter Testing feature in the box below to test your code
with different arguments.
Test Cases Are:
"arrb6???4xxbl5???eee5" true
"aa6?9" false
"acc?7??sss?3rr1??????5" true
My solution to this was to use RegExp to solve the challenge. the code below works well when I run it in the Browser, however, Coderbyte console throws an error every time:
/tmp/009904362/main.js:11 clean = clean.match(/d(???)d/gi); ^SyntaxError: Invalid regular expression: /d(???)d/
Here is my code -
function QuestionsMarks(str) {
//create a "clean" array containing only the numbers and question marks from str
var result;
let clean = str.match(/[0-9?]/g);
// join() the array back in to the string
clean = clean.join("");
// use match() to return an array of pairs that match the pattern d???d
clean = clean.match(/d(\?\?\?)d/gi);
//create a function sumCheck() that converts first and last char of every array string to Number and checks if the sum of digits is 10
//using forEach() run the sumcheck() on all strings in the array
clean.forEach(sumCheck);
function sumCheck(string){
if((Number(string.charAt(0)) + Number(string.charAt(string.length - 1))) == 10){
result = true;
}else{
result = false;
}
}
return result;
}
QuestionsMarks("acc?7??sss?3rr1??????5");
The problem seems to come from Coderbyte that isn't able to parse correctly escaped characters in regex patterns (literals or with the RegExp constructor). So the simplest solution is to replace escaped sequences: \d => [0-9], and \? => [?] (as suggested by #Saud in comments).
About your approach:
... check if there are exactly 3 question marks between every pair of two numbers that add up to 10 ...
What does your corrected pattern /[0-9][?]{3}[0-9]/g?It looks for digits separated by three question marks (and then you check if the sum of two digits is 10). Even if this pattern would be able to find all pair of digits separated by three question marks in the string (that isn't the case(*)), It doesn't check if there are digits that add up to 10 and that aren't separated by exactly 3 question marks!
So, the goal is to find if the string contains a pair of digits that add up to 10 without the 3 question marks. If this pair exists the function returns false.
(*): Why /[0-9][?]{3}[0-9]/g isn't able to find all pair of digits separated by 3 question marks?
Example with: 1???2???3???4
Because you can't match the same character twice. The pattern will find: 1???2 and 3???4 but not 2???3 since the 2 is already consumed by the first match.
A possible way to do it:
function QuestionsMarks(str) {
var state = { d1: 0, d2: 0, marks: 0,
init: function() { this.d1 = this.d2; this.marks = 0; },
check: function() { return this.d1 + this.d2 > 9 && this.marks != 3; }
};
var re = /[0-9?]/g;
var m;
while ( (m = re.exec(str)) !== null ) {
if ( m[0] == '?' ) {
state.marks++;
} else {
state.d2 = parseInt(m[0]);
if ( state.check() ) return false;
state.init();
}
}
return true;
}
I'm currently working with Javascript and for now I'm searching a way to check if variable contains at least one string. I have looked at previous questions, however, neither contain what I'm looking for. I have a function here:
function findCertainWords()
{
var t = {Some text value};
if (t in {'one':'', 'two':''})
return alert("At least one string is found. Change them."), 0;
return 1
}
Variable a is user's written text (for example, a comment or a post).
I want to check if user has written certain word in it and return an alert message to remove/edit that word. While my written function works, it only works when user writes that word exactly as I write in my variable ("Three" != "three"). I want to improve my funtion so it would also find case-insensitive ("Three" == "three") and part of words (like "thr" from "three"). I tried to put an expression like * but it didn't work.
It would be the best if every expression could be written in one function. Otherwise, I might need help with combining two functions.
Use indexOf to test if a string contains another string. Use .toLowerCase to convert it to one case before comparing.
function findCertainWords(t) {
var words = ['one', 'two'];
for (var i = 0; i < words.length; i++) {
if (t.toLowerCase().indexOf(words[i]) != -1) {
alert("At least one string was found. Change them.");
return false;
}
}
return true;
}
Another way is to turn the array into a regexp:
var regexp = new RegExp(words.join('|'));
if (regexp.test(t)) {
alert("At least one string was found. Change them.");
return false;
} else {
return true;
}
You can use Array.some with Object.keys
if(Object.keys(obj).some(function(k){
return ~a.indexOf(obj[k]);
})){
// do something
}
I've have a input string:
12345,3244,654,ffgv,87676,988ff,87657
I'm having a difficulty to transform all terms in the string that are not five digit numbers to a constant 34567 using regular expressions. So, the output would be like this:
12345,34567,34567,34567,87676,34567,87657
For this, I looked at two options:
negated character class: Not useful because it does not execute directly on this expression ,[^\d{5}],
lookahead and lookbehind: Issue here is that it doesn't include non-matched part in the result of this expression ,(?!\d{5}) or (?<!\d{5}), for the purpose of substitution/replace.
Once the desired expression is found, it would give a result so that one can replace non-matched part using tagged regions like \1, \2.
Is there any mechanism in regular expression tools to achieve the output as mentioned in the above example?
Edit: I really appreciate those who have answered non-regex solutions, but I would be more thankful if you provide a regex-based solution.
You don't need regex for this. You can use str.split to split the string at commas first and then for each item check if its length is greater than or equal to 5 and it contains only digits(using str.isdigit). Lastly combine all the items using str.join.
>>> s = '12345,3244,654,ffgv,87676,988ff,87657'
>>> ','.join(x if len(x) >= 5 and x.isdigit() else '34567' for x in s.split(','))
'12345,34567,34567,34567,87676,34567,87657'
Javascript version:
function isdigit(s){
for(var i=0; i <s.length; i++){
if(!(s[i] >= '0' && s[i] <= '9')){
return false;
}
}
return true;
}
arr = "12345,3244,654,ffgv,87676,988ff,87657".split(",");
for(var i=0; i < arr.length; i++){
if(arr[i].length < 5 || ! isdigit(arr[i])) arr[i] = '34567';
}
output = arr.join(",")
Try the following: /\b(?!\d{5})[^,]+\b/g
It constrains the expression between word boundaries (\b),
Followed by a negative look-ahead for non five digit numbers (!\d{5}),
Followed by any characters between ,
const expression = /\b(?!\d{5})[^,]+\b/g;
const input = '12345,3244,654,ffgv,87676,988ff,87657';
const expectedOutput = '12345,34567,34567,34567,87676,34567,87657';
const output = input.replace(expression, '34567');
console.log(output === expectedOutput, expectedOutput, output);
This approach uses /\b(\d{5})|(\w+)\b/g:
we match on boundaries (\b)
our first capture group captures "good strings"
our looser capture group gets the leftovers (bad strings)
our replacer() function knows the difference
const str = '12345,3244,654,ffgv,87676,988ff,87657';
const STAND_IN = '34567';
const massageString = (str) => {
const pattern = /\b(\d{5})|(\w+)\b/g;
const replacer = (match, goodstring, badstring) => {
if (goodstring) {
return goodstring;
} else {
return STAND_IN;
}
}
const r = str.replace(pattern,replacer);
return r;
};
console.log( massageString(str) );
I think the following would work for value no longer than 5 alphanumeric characters:
(,(?!\d{5})\w{1,5})
if longer than 5 alphanumeric characters, then remove 5 in above expression:
(,(?!\d{5})\w{1,})
and you can replace using:
,34567
You can see a demo on regex101. Of course, there might be faster non-regex methods for specific languages as well (python, perl or JS)
i try to allow only number 01 (1) to 53) after / and after 2000 and over....
so i create a regex but it don't seem to work
on this web page: http://www.regular-expressions.info/javascriptexample.html
i tried it and it work well... but when i test in on a web page
10/2010 , 23/2000
function isValidDate(value, format){
var isValid = true;
try{
var inputVal = $(this).val();
var dateWWYYYYRegex = '^(0[1-9]|[1234][0-9]|5[0-3])[-/.](20)\d\d$';
var reg=new RegExp(dateWWYYYYRegex);
if(!reg.test(value)){
isValid = false;
alert("Invalid");
}
}
catch(error){
isValid = false;
}
return isValid;
}
You have to escape backslashes if you're going to make a regex from a string. I'd just use regex syntax, since it's a constant anyway:
var reg = /^(0[1-9]|[1234][0-9]|5[0-3])[-/.](20)\d\d$/;
The regular expression doesn't really make any sense, however. It's not clear what it should be, because your description is also confusing.
edit — OK now that I see what you're doing, that regex should work, I guess.
Why use regex for this task? I think it's the wrong tool for this task
Simply split the string by the slash delimiter, and then use numerical functions to check if the values are in the range you want.
function isValidWeekOfYear(value){
var bits = value.split('/');
if(parseInt(bits[1]) < 2000) { return false; } /* probably also want to do a maximum value here? */
if(parseInt(bits[0]) < 1 || parseInt(bits[0]) > 53) { return false; }
return true;
}
It might need a bit more validation than that, but that should be a good starting point for you. Much less processing overhead than a regex just to parse a couple of numbers (and easier to read too).