javascript search string for sequential periods [duplicate] - javascript

This question already has answers here:
Regex to check consecutive occurrence of period symbol in username
(2 answers)
Closed 4 years ago.
How do I search a string for multiple periods in a row, for example "...".
string.search(/.../);
string.search("[...]");
The above will return true even if a single period is detected.
string.search("...");
This is even worse as it always returns true, even if there is no period.
var banlist = ["item1", "item2", "[...]"];
I am searching each string in the list, and I need to be able to search for "...".
Edit:
Now I have a new problem. three periods exactly "..." comes out to unicode character 8230, and it is not found in the search. Any other sequence of periods can be found except for three "...".

You need to escape the . character using a backslash \
let str = "som.e ra...ndom s.tring..";
console.log(str.match(/\.{2,}/g));
where {2,} indicates that there has to be at least 2 . characters in a row and /g indicates that the whole string should be evaluated. Notice that the . is escaped.

Use \\ to escape the dot in your search.
For example '\\.\\.' or '\\.{2}'
string.search() is useful for getting the index of the first occurrence of a pattern. It returns -1 if pattern isn't found.
string.search('\\.{2}')
With string.search going through the list would be something like
for (let i = 0; i < banlist.length; i++) {
if (banlist[i].search('\\.{2}') != -1) {
// Do something
}
}
If you don't need the index and just want to know if there are 2 or more dots in the string, string.match might be useful since it returns null when the pattern doesn't match.
string.match('\\.{2}')
With string.match going through the list would be something like
for (let i = 0; i < banlist.length; i++) {
if (banlist[i].match('\\.{2}')) {
// Do something
}
}

Related

Find how many times a char is repeated in a string and remove those repeated chars by a dynamic number

I would like to write a function that recieves two parameters: String and Number.
The function will return another string that is similar to the input string, but with certain characters
removed.
The function will remove characters from consecutive runs of the same
character, where the length of the run is greater than the input parameter.
for example:
"aaab", 2 => "aab"
"aabb", 1 => "ab"
"aabbaa", 1 => "aba"
What I did:
function doSomething(string,number) {
let repeatCount = 0
debugger;
for (let i = 0; i < string.length; i++) {
if(string[i] == string[i+1]){
repeatCount++
}
if(repeatCount > number ){
string.replace(string[i],'')
}
}
console.log(string)
}
doSomething('aaab',2)
The console.log(string) prints 'aaab' but I want it to print 'aab' because the number is 2 and the char 'a' is repeated 3 times.
If there is another better way to do it , I will be happy to learn.
If there is another better way to do it, I will be happy to learn.
You could go with a .replace() approach and a regular expression with a backreference to match consecutive letters. Then you can use .slice() to remove the additional letters to get it to the defined length like so:
function shorten(string,number) {
return string.replace(/(.)\1+/g, m => m.slice(0, number))
}
console.log(shorten("aaab", 2))// => "aab"
console.log(shorten("aabb", 1))// => "ab"
console.log(shorten("aabbaa", 1))// => "aba"
The above regular expression will match any character and group it (.). This matched character is then checked for again to see if it is repeated one or more times by using \1+. The replacement function will then be invoked for each consecutive runs of letters, which you can trim down to your desired length by using .slice().
For example, take the string aabbaa. The regular expression tries to find consecutive runs of characters. The (.) would match any character, in this case, it finds "a" and puts it into a "capture group" called "1". Now the regular expression tries to find whether “a” is followed by one or more “a” characters by checking if the grouped (ie the character “a”) follows it one or more times. This is done using \1+. The first section of the aabbaa string that this regular expression matches is "aa", as we match the “a”, capture it, and find that it is repeated with \1+. When a match is found, the function m => m.slice(0, number) is ran. This function takes the match (m), which in this case is "aa", and returns the sliced version of it, giving "a". This then replaces the "aa" we matched from the original string with the value returned, thus causing "aa" to be converted to "a" (note this conversion doesn't modify the original string, it occurs in the new string that gets returned by the replace method). The /g at the end of the regular expression means repeat this for the entire string. As a result, our regular expression moves on and finds "bb". The function then gets called again but this time with m set as "bb", causing "bb" to be converted to "b". Lastly, we match "aa", this causes "aa" to get converted to "a". Once replace has finished going through the entire string, it returns the result with the returned values (as well as the part of the original string it didn’t modify) and so it gives "aba"
Not that the rest of your code is correct. But one fundamental mistake you have made is that, strings in javascript is immutable. You cannot change an element of the string like that.
string.replace(string[i],'')
This won't change 'string'. You have to make another string from it.
let str = string.replace(string[i],'')
function doSomething(string,number) {
let repeatCount = 0
debugger
let sameletter=string[0]
for (let i = 0; i < string.length;i++) {
if(string[i] == sameletter){
repeatCount++
if(repeatCount>number){
var result = string.split('')
result.splice(i, 1)
string = result.join('')
i--
}
}
else{
sameletter=string[i];
repeatCount=1;
}
}
console.log(string)
}
doSomething('aaaabbbbeeeffffgggggggggg',2)
Try this

How to match one string by ignoring special character

I am implementing a searching technique by autosuggest and solr.
I am getting a bunch of matching strings with special characters. For example, if I search for
jp
The returned strings include:
jp,
j p ,
j.p.,
j.p. nag,
j-p-naga
I need to highlight all strings contains "jp" by ignoring special characters.
expected output like :
"j-p-naga"---- "j-p" should highlight({span}j-p{/span}-naga
You want to eliminate special characters? Use regular expressions:
function removeSpecials(str) {
return str.replace(/[^a-zA-Z0-9]/g, '');
}
console.log('jp' === removeSpecials('j .$##p##'));
console.log('jp' === removeSpecials('j.p.,');
// Both true
Or maybe you want to check if a string contains the character j followed by p in any location?
function strHasJP(str) { return /[^j]*j[^p]*p.*/.test(str); }
I'm not sure what you are trying to do. For help on RegExp, go here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions .

Tricky RegEx Capture [duplicate]

This question already has answers here:
My regex is matching too much. How do I make it stop? [duplicate]
(5 answers)
Closed 6 years ago.
I've got a couple strings and I need to pull characters out that appear between double quotes. The problem is, I want to grab them in groups.
var str = 'FF\"J"A4"L"';
var results = str.match(/\"(.*)\"/);
This returns everything between the first and last double quote. In this case it returns J"A4"L but what I need it to return is J and L.
The content between quotes is pretty much any unicode character like letters and numbers including as }, =, and #.
Any ideas on how to complete this with regex?
It sounds like the content between quotes is any character except for a quote, in which case you can get away with
/"([^"]*)"/
what you're looking for is this with the /g "global flag":
/("[^"]*")/g
In your example, it's like this:
var str = 'FF\"J"A4"L"';
var results = str.match(/("[^"]*")/g);
When doing this, results would be [""J"", ""L""], which contains the entire match (which is why the extra quotes are there).
If you wanted just the matched groups (which returns just the groups, not the whole match area), you would use exec:
var str = 'FF\"J"A4"L"';
var results = []
var r = /("[^"]*")/g
match = r.exec(str);
while (match != null) {
results.push(match[1])
match = r.exec(str);
}
Now, results is ["J", "L"]

How to split a string by a character not directly preceded by a character of the same type?

Let's say I have a string: "We.need..to...split.asap". What I would like to do is to split the string by the delimiter ., but I only wish to split by the first . and include any recurring .s in the succeeding token.
Expected output:
["We", "need", ".to", "..split", "asap"]
In other languages, I know that this is possible with a look-behind /(?<!\.)\./ but Javascript unfortunately does not support such a feature.
I am curious to see your answers to this question. Perhaps there is a clever use of look-aheads that presently evades me?
I was considering reversing the string, then re-reversing the tokens, but that seems like too much work for what I am after... plus controversy: How do you reverse a string in place in JavaScript?
Thanks for the help!
Here's a variation of the answer by guest271314 that handles more than two consecutive delimiters:
var text = "We.need.to...split.asap";
var re = /(\.*[^.]+)\./;
var items = text.split(re).filter(function(val) { return val.length > 0; });
It uses the detail that if the split expression includes a capture group, the captured items are included in the returned array. These capture groups are actually the only thing we are interested in; the tokens are all empty strings, which we filter out.
EDIT: Unfortunately there's perhaps one slight bug with this. If the text to be split starts with a delimiter, that will be included in the first token. If that's an issue, it can be remedied with:
var re = /(?:^|(\.*[^.]+))\./;
var items = text.split(re).filter(function(val) { return !!val; });
(I think this regex is ugly and would welcome an improvement.)
You can do this without any lookaheads:
var subject = "We.need.to....split.asap";
var regex = /\.?(\.*[^.]+)/g;
var matches, output = [];
while(matches = regex.exec(subject)) {
output.push(matches[1]);
}
document.write(JSON.stringify(output));
It seemed like it'd work in one line, as it did on https://regex101.com/r/cO1dP3/1, but had to be expanded in the code above because the /g option by default prevents capturing groups from returning with .match (i.e. the correct data was in the capturing groups, but we couldn't immediately access them without doing the above).
See: JavaScript Regex Global Match Groups
An alternative solution with the original one liner (plus one line) is:
document.write(JSON.stringify(
"We.need.to....split.asap".match(/\.?(\.*[^.]+)/g)
.map(function(s) { return s.replace(/^\./, ''); })
));
Take your pick!
Note: This answer can't handle more than 2 consecutive delimiters, since it was written according to the example in the revision 1 of the question, which was not very clear about such cases.
var text = "We.need.to..split.asap";
// split "." if followed by "."
var res = text.split(/\.(?=\.)/).map(function(val, key) {
// if `val[0]` does not begin with "." split "."
// else split "." if not followed by "."
return val[0] !== "." ? val.split(/\./) : val.split(/\.(?!.*\.)/)
});
// concat arrays `res[0]` , `res[1]`
res = res[0].concat(res[1]);
document.write(JSON.stringify(res));

getting contents of string between digits

have a regex problem :(
what i would like to do is to find out the contents between two or more numbers.
var string = "90+*-+80-+/*70"
im trying to edit the symbols in between so it only shows up the last symbol and not the ones before it. so trying to get the above variable to be turned into 90+80*70. although this is just an example i have no idea how to do this. the length of the numbers, how many "sets" of numbers and the length of the symbols in between could be anything.
many thanks,
Steve,
The trick is in matching '90+-+' and '80-+/' seperately, and selecting only the number and the last constant.
The expression for finding the a number followed by 1 or more non-numbers would be
\d+[^\d]+
To select the number and the last non-number, add parens:
(\d+)[^\d]*([^\d])
Finally add a /g to repeat the procedure for each match, and replace it with the 2 matched groups for each match:
js> '90+*-+80-+/*70'.replace(/(\d+)[^\d]*([^\d])/g, '$1$2');
90+80*70
js>
Or you can use lookahead assertion and simply remove all non-numerical characters which are not last: "90+*-+80-+/*70".replace(/[^0-9]+(?=[^0-9])/g,'');
You can use a regular expression to match the non-digits and a callback function to process the match and decide what to replace:
var test = "90+*-+80-+/*70";
var out = test.replace(/[^\d]+/g, function(str) {
return(str.substr(-1));
})
alert(out);
See it work here: http://jsfiddle.net/jfriend00/Tncya/
This works by using a regular expression to match sequences of non-digits and then replacing that sequence of non-digits with the last character in the matched sequence.
i would use this tutorial, first, then review this for javascript-specific regex questions.
This should do it -
var string = "90+*-+80-+/*70"
var result = '';
var arr = string.split(/(\d+)/)
for (i = 0; i < arr.length; i++) {
if (!isNaN(arr[i])) result = result + arr[i];
else result = result + arr[i].slice(arr[i].length - 1, arr[i].length);
}
alert(result);
Working demo - http://jsfiddle.net/ipr101/SA2pR/
Similar to #Arnout Engelen
var string = "90+*-+80-+/*70";
string = string.replace(/(\d+)[^\d]*([^\d])(?=\d+)/g, '$1$2');
This was my first thinking of how the RegEx should perform, it also looks ahead to make sure the non-digit pattern is followed by another digit, which is what the question asked for (between two numbers)
Similar to #jfriend00
var string = "90+*-+80-+/*70";
string = string.replace( /(\d+?)([^\d]+?)(?=\d+)/g
, function(){
return arguments[1] + arguments[2].substr(-1);
});
Instead of only matching on non-digits, it matches on non-digits between two numbers, which is what the question asked
Why would this be any better?
If your equation was embedded in a paragraph or string of text. Like:
This is a test where I want to clean up something like 90+*-+80-+/*70 and don't want to scrap the whole paragraph.
Result (Expected) :
This is a test where I want to clean up something like 90+80*70 and don't want to scrap the whole paragraph.
Why would this not be any better?
There is more pattern matching, which makes it theoretically slower (negligible)
It would fail if your paragraph had embedded numbers. Like:
This is a paragraph where Sally bought 4 eggs from the supermarket, but only 3 of them made it back in one piece.
Result (Unexpected):
This is a paragraph where Sally bought 4 3 of them made it back in one piece.

Categories

Resources