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
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
- What should happen with 10.01.23 => 10.01 or 10.0123? – Christoph Herold Commented Mar 15, 2019 at 19:18
- What with "a1b2c3d.e4f5g6h"? – trincot Commented Mar 15, 2019 at 19:20
- 10.0123 @ChristophHerold – Tiago Fernandez Commented Mar 15, 2019 at 19:24
- 123.456 @trincot – Tiago Fernandez Commented Mar 15, 2019 at 19:25
6 Answers
Reset to default 18With 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.
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));
You can do something like this, need two replace methods:
- For removing everything except digit and dot. For that use negated character class `[^\d.].
- For removing duplicate dots use replace with callback where we need to replace content after the first dot so use
\.([.\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)}`))
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.
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)
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.