2

I am trying to manipulate some float values inside of a string by a certain amount. To do so I have the following:

var string = '<path d="M219.6,-71.4C249,19.1,212.7,130.9,135.7,186.8C58.8,242.7,-58.8,242.7,-135.7,186.8C-212.7,130.9,-249,19.1,-219.6,-71.4C-190.2,-161.8,-95.1,-230.9,0,-230.9C95.1,-230.9,190.2,-161.8,219.6,-71.4Z" />';
var regex = /[+-]?([0-9]*[.])?[0-9]+/g;
console.log(string.replace(regex, parseFloat("$&") + 300));

How come it is replacing the parseFloat("$&") with NaN? What's the proper way to do this?

Zach Saucier
  • 24,871
  • 12
  • 85
  • 147

2 Answers2

4

Your code is equivalent to writing

var temp = parseFloat("$&") + 300;
document.body.innerText = string.replace(regex, temp);

because function arguments are evaluated before calling the function. "$&" only has special meaning if it's literally in the replacement string that replace() gets, it doesn't have any special meaning to parseFloat(), and it's not possible for replace() to reach into the parseFloat() call and modify the parameter.

If you want to call a function to determine the replacement, you need to pass a function reference to the replace() function, not an expression containing the function call.

var string = '<path d="M219.6,-71.4C249,19.1,212.7,130.9,135.7,186.8C58.8,242.7,-58.8,242.7,-135.7,186.8C-212.7,130.9,-249,19.1,-219.6,-71.4C-190.2,-161.8,-95.1,-230.9,0,-230.9C95.1,-230.9,190.2,-161.8,219.6,-71.4Z" />';
var regex = /[+-]?([0-9]*[.])?[0-9]+/g;
var newString = string.replace(regex, match => parseFloat(match) + 300);
console.log(newString)
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Thanks for the help! Apparently I missed the "`replacement` can be a string or a function to be called for each match" part of the documentation. – Zach Saucier Jun 28 '19 at 17:01
  • I settled on `match => Math.round((parseFloat(match) + 300.0001) * 100) / 100)` per [this post](https://stackoverflow.com/questions/11832914/round-to-at-most-2-decimal-places-only-if-necessary#comment28521418_11832950) to drop those pesky floating point errors. – Zach Saucier Jun 28 '19 at 17:34
  • If you want 2 decimal digits, use `toFixed(parseFloat(match)+300), 2)`. It will do the necessary rounding as well. – Barmar Jun 28 '19 at 18:15
  • Right, but that adds digits to numbers that don't have any, which I don't want. – Zach Saucier Jun 28 '19 at 18:50
1

See the parseFloat definition

A floating point number parsed from the given value. If the value cannot be converted to a number, NaN is returned.

So clearly you have a string there which can't be converted to a Number.

Zach Saucier
  • 24,871
  • 12
  • 85
  • 147
Shubham Dixit
  • 9,242
  • 4
  • 27
  • 46
  • 1
    Right, but if I change the replace to "" it removes all of them, so it's matching them properly - the real question is what's the proper way to parse them. Not what happens if it can't be parsed using `parseFloat`. – Zach Saucier Jun 28 '19 at 16:54