Skip to content
Advertisement

Advice on how to resolve an issue with extracting only numbers from a string using JavaScript

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.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement