1

I came answers (below) to try and understand how consecutive lookaheads work. My understanding seems to be contradictory and was hoping someone could help clarify.

The answer here suggests that all the lookaheads specified must be present for the first matched character (Why consecutive lookaheads do not always work answer by Sam Whan)

If I apply that to the solution in this answer: How to print a number with commas as thousands separators in JavaScript:

function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

it means that it's looking for the a non-boundary character that is followed by a sequence of characters with length that is a multiple of 3 and at the same time followed by characters that are not digits.

e.g. 12345 Knowing that a comma should go after the 2 but it seems contradictory as 2 has 3 digits following it, satisfying the first lookahead but the second lookahead contradicts it as it's supposed to not be followed by any digits.

I'm sure I'm misunderstanding something. Any help is appreciated. Thanks!

jjkl
  • 353
  • 6
  • 15

1 Answers1

1

This regex:

/\B(?=(\d{3})+(?!\d))/g

Has only one positive lookahead condition and other negative lookahead is inside this first lookahead.

Here are details:

  • \B: Match position where \b doesn't match (e.g. between word characters)
  • (?=: Start lookahead
    • (\d{3})+: Match one or more sets of 3 digits
    • (?!\d): Inner negative lookahead to assert that we don't have a digit after match set of 3 digits
  • ): End lookahead

However do note that it is much better to use following code to format your number to a thousand separator string:

console.log( parseFloat('1234567.89').toLocaleString('en') )
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    Thanks for your response. Is my understanding correct that because the second lookahead is nested inside the first, its lookahead is based off of the 3 digits/multiple of 3 digits that follow our initial matched character? So for `12345` it matches the space between 2 and 3 and then looks to see if the 345 is followed by any digits. In this case it's not so the lookaheads are satisfied and comma placed between 2 and 3? – jjkl Apr 07 '20 at 21:44
  • That is absolutely correct but just one tiny correction that there is no space between `2` and `3` in `12345`. It is called zero width assertion matched by `\B` and satisfied by lookahead assertions of having multiple of 3 digits ahead that must not be followed by another digit. – anubhava Apr 07 '20 at 21:51