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

Time:07-30

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

/\b\d \.?\d*\b/g

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))

  • Related