Reputation: 1473
This works for integers, e.g.:
'123x'.replace(/\D/g, '')
'123'
Which regular expression would achieve the same, but allowing only one dot? Examples:
1
-> 1
1x
-> 1
10.
-> 10.
10.0
-> 10.0
10.01
-> 10.01
10.01x
-> 10.01
10.01.
-> 10.01
Upvotes: 4
Views: 4845
Reputation: 408
This would be a good and simple solution if you want to trim everything but numbers along with only the first occurrence of the dots.
"ab12..34..c".replace(".", "~").replace(/[^0-9~]/g, "").replace("~", ".")
OUTPUT: 12.34
1s replace: Assigning the first dot (.) to tilde (~). 2nd replace: Keeping only numbers and the tilde (there is only one). 3rd replace: Replacing tilde with dot.
Upvotes: 0
Reputation: 350272
With two replaces:
console.log("a12b3.1&23.0a2x".replace(/[^.\d]/g, '')
.replace(/^(\d*\.?)|(\d*)\.?/g, "$1$2"));
The first action will remove all characters other than digits and points
The second replacement matches sequences of digits possibly followed by a point, but it does so in two different ways. When such sequence occurs at the start of the string, the optional point is put inside the first capture group, while for all other matches, the point is outside the (second) capture group.
There are two capture groups, but for any given match, only one of them will actually have content. So the captured content can be reproduced in either case with $1$2
. This will include the first point, but exclude any other.
Upvotes: 18
Reputation: 1809
UPDATE
Why not simply do it old school:
function formatNumber(s) {
var hadDot = false, result = '';
for (var i = 0; i < s.length; i++) {
var c = s[i];
if (c >= '0' && c <= '9')
result += c;
else if (!hadDot && c == '.') {
hadDot = true;
result += c;
}
}
return result;
}
var inputs = ['10.01.x23.5asd6', '10.', '10', '.12vx12.1f53', '10.10.'];
for (var i = 0; i < inputs.length; i++) {
console.log(formatNumber(inputs[i]));
}
Requires just one iteration of the string, so you probably won't get any better running time.
OLD ANSWER, WON'T WORK
This should also work (but it doesn't, thanks to trincot for pointing it out):
function formatNumber(s) {
return s.replace(/[^\d\.]/g, '').replace(/\.(([^\.]*)\.)*/g, '.$2');
}
var inputs = ['10.01.x23.5asd6', '10.', '10', '.12vx12.1f53', '10.10.'];
for (var i = 0; i < inputs.length; i++) {
console.log(formatNumber(inputs[i]));
}
First, replace all non-digits and dots. Then, capture everything after the first dot, and replace it with anything that is not a dot. But, it needs a two step regex.
Upvotes: 1
Reputation: 217
let arr = ['1', '1x', '10.', '10.0', '10.01', '10.01x', '10.01.', '10.01.23', 'a1b2c3d.e4f5g6h'];
arr.forEach(val => {
val = val.replace(/[^\d.]/g, '').match(/([0-9]+(\.[0-9]*)?)/);
if (val) console.log(val[0]);
})
replace(/[^\d.]/g, '')
to replace any non-digit character and non .
character.
[0-9]+
digits from 0 to 9 will be matched, and +
for match one or more time
.
followed by a dot.
[0-9]*?
matched from 0 to 9 (but match ZERO or more time)
Upvotes: 0
Reputation: 115222
You can do something like this, need two replace methods:
\.([.\d]+)$
to match entire string after first do(including the dot) and within callback remove all the remaining dots from the captured value(string after the first dot).'123x'.replace(/[^\d.]/g, '').replace(/\.([.\d]+)$/,function(m,m1){
return '.' + m1.replace(/\./g, '')
})
DEMO :
var arr = ['1', '1x', '10.', '10.0', '10.01', '10.01x', '10.01.', '10.01.23', 'a1b2c3d.e4f5g6h'];
function format(str) {
return str.replace(/[^\d.]/g, '').replace(/\.([.\d]+)$/, function(m, m1) {
return '.' + m1.replace(/\./g, '')
});
}
arr.forEach((v) => console.log(`${v} => ${format(v)}`))
Upvotes: 1
Reputation: 386604
You could use parseFloat
and convert back to a string.
console.log(parseFloat('10.01.x').toString());
An approach with a regular expression.
function convert(s) {
return s.match(/^\d+\.?\d*/)[0];
}
console.log(['1', '1x', '10.', '10.0', '10.01', '10.01x', '10.01.'].map(convert));
Upvotes: 3