I have IDs that look like: 185-51-671 but they can also have letters at the end, 175-1-7b
All I want to do is remove the hyphens, as a pre-processing step. Show me some cool ways to do this in javascript? I figure there are probably quite a few questions like this one, but I'm interested to see what optimizations people will come up with for "just hyphens"
Thanks!
edit: I am using jQuery, so I guess .replace(a,b) does the trick (replacing a with b)
numberNoHyphens = number.replace("-","");
any other alternatives?
edit #2:
So, just in case anyone is wondering, the correct answer was
numberNoHyphens = number.replace(/-/g,"");
and you need the "g" which is the pattern switch or "global flag" because
numberNoHyphens = number.replace(/-/,"");
will only match and replace the first hyphen
You need to include the global flag:
var str="185-51-671";
var newStr = str.replace(/-/g, "");
This is not faster, but
str.split('-').join('');
should also work.
I set up a jsperf test if anyone wants to add and compare their methods, but it's unlikely anything will be faster than the replace method.
http://jsperf.com/remove-hyphens-from-string
var str='185-51-671';
str=str.replace(/-/g,'');
Gets much easier in String.prototype.replaceAll(). Check out the browser support for the built-in method.
const str = '185-51-671';
console.log(str.replaceAll('-', ''));
Som of these answers, prior to edits, did not remove all of the hyphens. You would need to use .replaceAll("-","")
In tidyverse, there are multiple functions that could suit your needs. Specifically, I would use str_remove, which will replace in a string, the giver character by an empty string (""), effectively removing it (check here the documentation). Example of its usage:
str_remove(x, '-')
Related
I have to explicitly use trim() for too many variables. Is there anyway I can apply trim to all the string values in code without calling trim explicitly?
Note:
I asked this question out of curiosity to find if there is a way or possibility to do so. Even I dont want to apply trim in all the scenarios. But yes I've to use trim for all the literals and variables I use in an app(I've such a req). So wanted to know if there is a common place where I can change instead of missing few places.
No, there's nothing in JavaScript's strings that will globally enable automatic whitespace trimming for you. You'll have to do it when/where required, which should typically be only a few places (e.g., reading from inputs).
Here's a cool hack. would not recommend:
String.prototype.valueOf = function() {
return this.trim();
};
'query' + (new String(' asdf ')); // "queryasdf"
I need to split a string to one or more substrings each of which contains no more or less than two dots. For example, if the string is foo.boo.coo.too" then what would be the regex to get the following array?: ["foo.boo.coo", "boo.coo.too"]. I hope there will be someone to answer this question - I will really admire you, as I've been programming for several years and have not still be used to regular expressions well enough to solve this particular problem by myself. Thank you very much in advance. Let me know your identity so that I can credit you as a contributor of the program I am creating.
RegEx is for this Problem not the best solution a similar problem was discussed here: split-a-sting-every-3-characters-from-back-javascript
A good javascript solution would be a javascript function like this
function splitter(text){
var parts = text.split(".");
var times = parts.length - 2;
var values = [];
for(var index = 0; index<times;index++)
{
values.push(parts.slice(index,index+3).join("."));
}
return values;
}
splitter("too.boo.coo.too")
//=> Result tested on Chrome 25+ ["too.boo.coo", "boo.coo.too"]
I hope this helps
If you want to Use Regex try the Lookhead Stuff, this could help http://www.regular-expressions.info/lookaround.html
Regex by its nature will return non-intersecting results, so if you want "all matches" from a single regex - it's not possible.
So basically you will need to find first match, and then start from next position to find next match and so on; something like this technique described here regex matches with intersection in C# (it's not JavaScript but idea is the same)
You can use the following regex for example:
(?<=^|\.)((?:[^.]*\.){2}[^.]*?)(?=$|\.)
It ensures that it starts and ends with dot, or at begin/end of line, and contains exactly two dots inside, and captures result in first capture. You can replace * with + to make sure at least one symbol exists between dots, if it is required.
But you need to understand that such approach has really bad performance for the task you are solving, so may be using other way (like split + for) will be better solution.
I was wondering about Javascript performance about using string.replace() or string.substr(). Let me explain what I'm doing.
I've a string like
str = "a.aa.a.aa."
I just have to "pop" last element in str where I always know what type of character it is (e.g, it's a dot here).
It's so simple, I can follow a lot of ways, like
str = str.substr(0, str.length-1) // same as using slice()
or
str = str.replace(/\.$/, '')
Which methods would you use? Why? Is there some lack in performance using this or that method? Length of the string is negligible.
(this is my first post, so if I'm doing something wrong please, notify me!)
For performance tests in JavaScript use jsPerf.com
I created a testcase for your question here, which shows, that substr is a lot faster (at least in firefox).
If you just want the last character in the string, then use the subscript, not some replacement:
str[str.length-1]
Do you have to do this thousands of times in a loop? If not (and "Length of string is negligible"), any way will do.
That said, I'd prefer the first option, since it makes the intention of trimming the last character more clear than the second one (oh, and it's faster, in case you do need to run this a zillion times. Since in the regex case, you need to not only build a new string but also compile a RegExp and run it against the input.)
When you have this kind of doubt, either pick what you like the best (style-speaking, as running this only once doesn't matter much), or use http://jsperf.com.
For this very example, see here why substr is better :-).
The substr way should always be faster than any kind of RegExp. But the performance difference should be minor.
I am trying to parse a string in this format
[something](something something) [something](something something)
and I want to break on every space that is not between a set of parenthesis?
I tried using js string.split with this as the regex /[^\(].*\s+.*[^\)]/g, but it doesn't work? Any suggestions appreciated :-)
EDIT: I don't want to post this as an answer, because I want to leave it open to comments but I finally found a solution.
var a = "the>[the](the the) the>[the](the the) the"
var regex = /\s+(?!\w+[\)])/
var b = a.split(regex)
alert(b.join("+++"))
Is your input always this consistent? If it is, it could be as simple as splitting your string on ') ['
If it isn't, is it possible to just take what is between [ and )? Or is there some kind of nesting that is going on?
You are using the wrong tool for the job.
As was alluded to in this famous post, regular expressions cannot parse non-regular languages, and the "balanced parenthesis" problem cannot be described by a regular language.
Have you tried writing a parser instead?
EDIT:
It seems that you've finally clarified that nesting is not a requirement. In that case, I'd suggest gnur's solution.
This regex will do exactly what you asked, and nothing more:
'[x](x x) [x](x x)'.split(/ +(?![^\(]*\))/);
I am trying to write some JavaScript RegEx to replace user inputed tags with real html tags, so [b] will become <b> and so forth. the RegEx I am using looks like so
var exptags = /\[(b|u|i|s|center|code){1}]((.){1,}?)\[\/(\1){1}]/ig;
with the following JavaScript
s.replace(exptags,"<$1>$2</$1>");
this works fine for single nested tags, for example:
[b]hello[/b] [u]world[/u]
but if the tags are nested inside each other it will only match the outer tags, for example
[b]foo [u]to the[/u] bar[/b]
this will only match the b tags. how can I fix this? should i just loop until the starting string is the same as the outcome? I have a feeling that the ((.){1,}?) patten is wrong also?
Thanks
The easiest solution would be to to replace all the tags, whether they are closed or not and let .innerHTML work out if they are matched or not it will much more resilient that way..
var tagreg = /\[(\/?)(b|u|i|s|center|code)]/ig
div.innerHTML="[b][i]helloworld[/b]".replace(tagreg, "<$1$2>") //no closing i
//div.inerHTML=="<b><i>helloworld</i></b>"
AFAIK you can't express recursion with regular expressions.
You can however do that with .NET's System.Text.RegularExpressions using balanced matching. See more here: http://blogs.msdn.com/bclteam/archive/2005/03/15/396452.aspx
If you're using .NET you can probably implement what you need with a callback.
If not, you may have to roll your own little javascript parser.
Then again, if you can afford to hit the server you can use the full parser. :)
What do you need this for, anyway? If it is for anything other than a preview I highly recommend doing the processing server-side.
You could just repeatedly apply the regexp until it no longer matches. That would do odd things like "[b][b]foo[/b][/b]" => "<b>[b]foo</b>[/b]" => "<b><b>foo</b></b>", but as far as I can see the end result will still be a sensible string with matching (though not necessarily properly nested) tags.
Or if you want to do it 'right', just write a simple recursive descent parser. Though people might expect "[b]foo[u]bar[/b]baz[/u]" to work, which is tricky to recognise with a parser.
The reason the nested block doesn't get replaced is because the match, for [b], places the position after [/b]. Thus, everything that ((.){1,}?) matches is then ignored.
It is possible to write a recursive parser in server-side -- Perl uses qr// and Ruby probably has something similar.
Though, you don't necessarily need true recursive. You can use a relatively simple loop to handle the string equivalently:
var s = '[b]hello[/b] [u]world[/u] [b]foo [u]to the[/u] bar[/b]';
var exptags = /\[(b|u|i|s|center|code){1}]((.){1,}?)\[\/(\1){1}]/ig;
while (s.match(exptags)) {
s = s.replace(exptags, "<$1>$2</$1>");
}
document.writeln('<div>' + s + '</div>'); // after
In this case, it'll make 2 passes:
0: [b]hello[/b] [u]world[/u] [b]foo [u]to the[/u] bar[/b]
1: <b>hello</b> <u>world</u> <b>foo [u]to the[/u] bar</b>
2: <b>hello</b> <u>world</u> <b>foo <u>to the</u> bar</b>
Also, a few suggestions for cleaning up the RegEx:
var exptags = /\[(b|u|i|s|center|code)\](.+?)\[\/(\1)\]/ig;
{1} is assumed when no other count specifiers exist
{1,} can be shortened to +
Agree with Richard Szalay, but his regex didn't get quoted right:
var exptags = /\[(b|u|i|s|center|code)](.*)\[\/\1]/ig;
is cleaner. Note that I also change .+? to .*. There are two problems with .+?:
you won't match [u][/u], since there isn't at least one character between them (+)
a non-greedy match won't deal as nicely with the same tag nested inside itself (?)
Yes, you will have to loop. Alternatively since your tags looks so much like HTML ones you could replace [b] for <b> and [/b] for </b> separately. (.){1,}? is the same as (.*?) - that is, any symbols, least possible sequence length.
Updated: Thanks to MrP, (.){1,}? is (.)+?, my bad.
How about:
tagreg=/\[(.?)?(b|u|i|s|center|code)\]/gi;
"[b][i]helloworld[/i][/b]".replace(tagreg, "<$1$2>");
"[b]helloworld[/b]".replace(tagreg, "<$1$2>");
For me the above produces:
<b><i>helloworld</i></b>
<b>helloworld</b>
This appears to do what you want, and has the advantage of needing only a single pass.
Disclaimer: I don't code often in JS, so if I made any mistakes please feel free to point them out :-)
You are right about the inner pattern being troublesome.
((.){1,}?)
That is doing a captured match at least once and then the whole thing is captured. Every character inside your tag will be captured as a group.
You are also capturing your closing element name when you don't need it and are using {1} when that is implied. Below is a cleanup up version:
/\[(b|u|i|s|center|code)](.+?)\[\/\1]/ig
Not sure about the other problem.