Reputation: 678
I trying to do a function to replace all the character after a certain length of character to asterisk, and so far what i did is like this.
var text = 'ABCDEFG';
var newText = text.substring(0,3) + text.substring(3).replace(/\S/g,'*');
If would give me what I need, but it is fairly inefficient as I understand it, and i trying to change it to make it more efficient.
text.replace(/.{4}$/,'*');
Unfortunately the result is not i expected and also it need to be hardcode the length of 4 counting from behind, which it wont work if the word's length is different.
Is there any regex method that able to replace all other character to asterisk after certain length of character (in this case is 3).
Any help to this will be appreciated. Thanks.
Edited: As conclusion of the suggestion and discussion
Alternative way to solve the problem, which giving the almost identical result as my solution.
text.replace(/(\w{3}).*/g, "$1"+(new Array(text.length -3 + 1).join( '*' )));
by @Keerthana Prabhakaran
text.replace(new RegExp(".(?=.{0," + (text.length-4) + "}$)", "g"), '*')
by @Wiktor Stribiżew
var longerThanNeeded = "***************************";
var newText = text.substring(0,3) + longerThanNeeded.substring(0,text.length-3);
by @matthewninja
(^.{3}).|. and replace w/ \1*
by @alpha bravo
As discuss with some of the people, due to the efficiency of the code are almost the same even for the original code that I make of. Therefore it stated as side discussing.
Appreciated the helps once again.
Upvotes: 4
Views: 3436
Reputation: 626738
You may use
s.replace(new RegExp(".(?=.{0," + (s.length-4) + "}$)", "g"), '*')
See a JS demo:
var text = 'ABCDEFG';
var threshold = 3; // Start replacing with * after this value
if (text.length > threshold) {
text = text.replace(new RegExp(".(?=.{0," + (text.length-threshold-1) + "}$)", "g"), '*');
}
console.log(text);
Here, if threshold
is 3
, the pattern will look like .(?=.{0,3}$)
: it matches any char but a line break char with .
that is followed with 0 to 3 chars other than line break chars (.{0,3}
) and the end of string position ($
). The (?=...)
is a positive lookahead that only checks for the pattern match, but does not move the regex index and does not add the matched text to the match value (allowing subsequent consecutive symbol check).
To enable matching line breaks, replace .
with [^]
or [\s\S]
.
Upvotes: 1
Reputation: 370
I hope I'm not overthinking this.
text.substring(3).replace(/\S/g,'*');
has linear time complexity O(n)
and isn't terribly inefficient.
I initially thought of using Array.prototype.join()
like so:
var newText = text.substring(0,3) + Array(text.length-2).join("*");
Before realizing that .join() needs to run for every element of the array, which results in linear time complexity, just like your original solution. This wouldn't improve the solution at all; All I've done is inflate the space complexity.
I then went on to think of creating the element to be joined by copying and increasing the size of the prior element, which would get us down to 0(log n)
complexity.
Finally, I saw the most obvious solution.
var longerThanNeeded = "***************************";
var newText = text.substring(0,3) + longerThanNeeded.substring(0,text.length-3);
which will run in constant time.
Upvotes: 3
Reputation: 7948
You could use this pattern (^.{3}).|.
and replace w/ \1*
Demo
(Please note limitation for strings less than 3 characters in length)
( # Capturing Group (1)
^ # Start of string/line
. # Any character except line break
{3} # (repeated {3} times)
) # End of Capturing Group (1)
. # Any character except line break
| # OR
. # Any character except line break
Upvotes: 2