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)
Advertisement
Answer
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.