2

I would like a simple way to replace the digit at a specific "place value" using javascript. For example if i had the number 1234.567, i might want to replace the hundreds digit with a 1 so that my new number is 1134.567.

For my specific application i am dealing with money so i am ensured that my number only has 2 decimal places. knowing this i could implement something like the following:

const reversed = String(myNumber).split("").reverse().join("");
const digitIndex = myDigit + 2; // where myDigit is the digit i want 
to replace (ones = 0, tens = 1, etc)

String.prototype.replaceAt=function(index, replacement) {
  return this.substr(0, index) + replacement+ this.substr(index + 
  replacement.length);
}

const replaced = reversed.replaceAt(digitIndex, myReplacement);
return parseFloat(replaced.split("").reverse().join(""));

The idea is to reverse the string because i dont know how big the number will be, replace the digit and then reverse again and turn it back into a number. This definitely seems like overkill. Any better ideas?

user3666653
  • 188
  • 1
  • 7
  • 1
    Looks like this problem was already addressed here: https://stackoverflow.com/questions/1431094/how-do-i-replace-a-character-at-a-particular-index-in-javascript – André Baptista Dec 21 '18 at 18:04
  • no, that problem is specifically for replacing chars at a string index (and ive actually borrowed some of that code for my solution above) – user3666653 Dec 21 '18 at 18:12

2 Answers2

4

Here's a way to do it with a regex:

RegExp(`\\d(?=\\d{${index - 1}}(\\.|$))`)

Explanation

(?=\\d{${index - 1}}(\\.|$)) non-capturing forward lookahead which matches index - 1 digits followed by either a decimal or the end of the string

\\d single digit to replace, if the forward lookahead has been matched

String.prototype.replaceAt = function(index, replacement) {
  const re = new RegExp(`\\d(?=\\d{${index - 1}}(\\.|$))`);
  return this.replace(re, replacement);
}

const tests = [
  {test: '123.45', index: 1},
  {test: '123.45', index: 2},
  {test: '123.45', index: 3},
  {test: '123', index: 1},
  {test: '123', index: 2},
  {test: '123', index: 3}
];

tests.forEach(({test, index}) => {
  console.log(test.replaceAt(index, 'x'))
})

Update:

You can use this to extend Number:

Number.prototype.replaceAt = function(index, replacement) {
  const re = new RegExp(`\\d(?=\\d{${index - 1}}(\\.|$))`);
  return parseFloat(`${this}`.replace(re, replacement));
}

const tests = [
  {test: 123.45, index: 1},
  {test: 123.45, index: 2},
  {test: 123.45, index: 3},
  {test: 123, index: 1},
  {test: 123, index: 2},
  {test: 123, index: 3}
];

tests.forEach(({test, index}) => {
  console.log(test.replaceAt(index, 9))
})

Update:

Here's a way to do it with pure math

Number.prototype.replaceAt = function(index, val) {
  const a = parseInt(this / 10 ** index) * 10 ** index;
  const b = val * 10 ** (index - 1);
  const c = this % 10 ** (index - 1);
  return a + b + c;
}

const tests = [
  {test: 123.45, index: 1},
  {test: 123.45, index: 2},
  {test: 123.45, index: 3},
  {test: 123, index: 1},
  {test: 123, index: 2},
  {test: 123, index: 3}
];

tests.forEach(({test, index}) => {
  console.log(test.replaceAt(index, 9))
})
ic3b3rg
  • 14,629
  • 4
  • 30
  • 53
1

To achieve expected result, use below option

  1. pass three parameters - number , position, replace
  2. Using position , update with replace number

Detailed explanation of return value for number 1223.45

num % pos - 1223.45 % 100 = 23.45
rep * pos - 7 * 100 = 700
parseInt((num / pos)/10)*pos*10 = 1*pos*10 = 1000

function format(num, pos, rep){
    return num % pos + (rep * pos) + parseInt((num / pos)/10)*pos*10
}

console.log(format(1223.45, 1000, 7));
console.log(format(1223.45, 100, 7));
console.log(format(1223.45, 10, 7));
console.log(format(1223.45, 0.1, 7));
console.log(format(1223.45, 0.01, 7));

codepen - https://codepen.io/nagasai/pen/xmqjdd?editors=1010

Naga Sai A
  • 10,771
  • 1
  • 21
  • 40