I'm new to stackoverflow and would appreciate some advice to help me solve this problem. I have two strings that I want to extract numbers from
String 1 = "12.3,Name1,3,4,Name2,35,Name3"
returns [12.3,3,4,35]
Which is the required result.
String 2 = "12.3,22,Q"
returns [12.322]
Which is the incorrect result, It should be [12.3,22]
I have commented on my code with the steps I have taken to complete the task. Again many thanks for your advice and help in advance.
Here is a copy of my code:
function extractNumbers(str) {
//Use replace() to replace all instances of letters/alpha*
let onlyNumbersString = str.replace(/[a-z]/ig, '');
//remove "," using replace()*
onlyNumbersString = onlyNumbersString.replace(",", "");
//Create an array of numbers*
let arrayOfNumbers = onlyNumbersString.split(',');
let result = arrayOfNumbers.map((x) => parseFloat(x))
console.log(arrayOfNumbers)
console.log(result);
const filtered = result.filter(function(e) {
return e
})
console.log(filtered)
}
let numbers = "12.3,Name1,3,4,Name2,35,Name3" //returns [12.3,3,4,35]
//"12.3,22,Q" returns [12.322]*
extractNumbers(numbers)
CodePudding user response:
The incorrect result is because of this line:
onlyNumbersString = onlyNumbersString.replace(",", "");
Once you do that, "12.3,22,"
(which was "12.3,22,Q"
but had the Q
removed before) becomes "12.322"
, so that looks like a single number.
I'd split first, then remove the segments that have non-number text in them, then convert to number:
function extractNumbers(str) {
// Split on commas, since that seems to be the delimiter you want
const parts = str.split(",");
// Remove any strings that aren't all number chars (including `.`)
const filtered = parts.filter((s) => !/[^.\d]/.test(s));
// Convert to number
const numbers = filtered.map((s) => parseFloat(s));
return numbers;
}
console.log(extractNumbers("12.3,Name1,3,4,Name2,35,Name3"));
Or without comments:
function extractNumbers(str) {
const parts = str.split(",");
const filtered = parts.filter((s) => !/[^.\d]/.test(s));
const numbers = filtered.map((s) => parseFloat(s));
return numbers;
}
You could make it a single statement, but it becomes harder to debug:
function extractNumbers(str) {
return str
.split(",")
.filter((s) => !/[^.\d]/.test(s))
.map((s) => parseFloat(s));
}
I should note that the only reason to check that a segment is valid is that parseFloat
will happily accept "123abc"
, returning 123
and ignoring the rest. You could use the unary
operator or the Number
function instead, checking for the ""
case (which would give you 0
if you didn't weed it out):
function extractNumbers(str) {
const parts = str.split(",");
const numbers = parts.map((s) => s.trim() ? s : NaN);
const validNumbers = numbers.filter((num) => !isNaN(num));
return validNumbers;
}
console.log(extractNumbers("12.3,Name1,3,4,Name2,35,Name3"));
My answer here goes through the various options for converting strings to numbers and the pitfalls of each of them.
CodePudding user response:
You can simply split on ,
and check if it's a valid number of not
function extractNumbers(str) {
let onlyNumbersString = str.split(',').filter(v => /^\d (\.\d )?$/.test(v))
console.log(onlyNumbersString)
}
let numbers = "12.3,Name1,3,4,Name2,35,Name3" //returns [12.3,3,4,35]
//"12.3,22,Q" returns [12.322]*
extractNumbers(numbers)
extractNumbers('12.3,22,Q')
If you don't want to use regex, you can use isNaN
let onlyNumbersString = str.split(',').filter(v => v.trim() && !isNaN(v))
CodePudding user response:
I think you can build the desired output by using the following regex
This is assuming there are no strings like Name2 45
const str = "12.3,Name1,3,4,Name2,35,Name3";
console.log(str.match(/\b\d \.?\d*\b/g))