0

I am searching through text contained in multiple DIVS looking for an occurrence of a substring within a string.

Example: Searching for '1st', finding a match in the string (101st), and then i want to replace the entire string (101st) with another string (one hundred first).

I can locate the occurrence, but I can't figure out how to return the ENTIRE word the substring occurs in to replace it.

The scenario: The DIVS contain driving directions that contains street numbers. I am converting the numbered streets to words in order for the text to speech engine to correctly pronounce the numbers. So there may be a 91st which I would replace with ninety first, or a 21st that I would replace with twenty first. I have a function already written that will take care of any possible combinations of replacement words. I just need to figure out how to capture the entire string of the occurrence to implement the replace().

The reason I need the entire string (word) that the occurrence is in, is because the function numberToWords.toWordsOrdinal() I will pass the string to will take the entire string (101st) and convert it to one hundred first. I'm searching for all numbers ending in 0th, 1st, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th and 9th and converting to the word version of the numbers. Any numbers that do not contain an ordinal will be left alone.

Here is the code I have:

$("div.dirInstruction").each(function() {
  if ($(this).text().indexOf("1st") >= 0) {
    // found occurrence
    alert($(this).text()); // < ---- for visual debug - returns all text in div of match
    var StringThatContainsMatch = ?????;  <----- need whole word that contained match
    var replaceNumber = numberToWords.toWordsOrdinal(StringThatContainsMatch);
    var new_word = $(this).text().replace(StringThatContainsMatch, replaceNumber);
    $(this).text(new_text);
  }
});
Rodney
  • 514
  • 1
  • 9
  • 27
  • Do you want to replace *all* strings which contain `1st` with `one hundred first`? That sounds a bit odd. Or do you have a lookup table or something? – CertainPerformance Oct 26 '19 at 06:43
  • Not necessarily. It is driving directions that contains street numbers. I am converting the numbered streets to words in order for the text to speech engine to correctly pronounce the numbers. So there may be a 91st which I would replace with ninety first. I have a function already written that will take care of any possible combinations. I just need to figure out how to capture the entire string of the occurrence to implement the replace. – Rodney Oct 26 '19 at 06:45

3 Answers3

2

Since you already have a function that takes care of the hard part, you can use .replace with a replacer function that takes in the matched digits, and replaces them with the appropriate string, taken from the other function call:

function translateDigits(_, digits) {
  // Logic to turn, eg, 101 into "one hundred first"
  return 'one hundred first';
}

$("div.dirInstruction").each(function(){
  this.textContent = this.textContent.replace(
    /(\d+)st\b/g,
    translateDigits
  )
});

The \d+ will match the digits which are followed by st and a word boundary, and then they'll be passed to translateDigits as the second argument (the first argument is the whole matched string, which isn't needed - we don't need to look at the st).

To also match words ending in other numeric-terminators, alternate the st with them as well:

function translateDigits(_, digits) {
  // Logic to turn, eg, 101 into "one hundred first"
  return 'one hundred first';
}

$("div.dirInstruction").each(function(){
  this.textContent = this.textContent.replace(
    /(\d+)(?:st|nd|rd|th)\b/g,
    translateDigits
  )
});

The (?:st|nd|rd|th) part will help match number strings 1st / 2nd / 3rd / 4th etc.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • I am calling my function with numberToWords.toWordsOrdinal(StringThatContainsMatch ); How would I implement this into your code? – Rodney Oct 26 '19 at 07:08
  • Do you mean you want to include the `st` part? (seems like just having the number itself would be a bit easier) If you need the `st`, just remove the capturing group, and match `\d+st\b` – CertainPerformance Oct 26 '19 at 07:11
  • In instances when the street address might be 121 Main Street there are no issues. But when the street address might be 121st East Avenue that is when it can't properly interpret the number for pronunciation that's why I'm searching for all numbers ending in 0th, 1st, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th and 9th and converting to the word version of the numbers to correct the issue. – Rodney Oct 26 '19 at 07:15
  • Ok, then alternate the `st` with the other numeric-terminators in the regular expression – CertainPerformance Oct 26 '19 at 07:19
  • Okay so I would place my function to translate the numbers inside your translateDigits(_, digits) function ? – Rodney Oct 26 '19 at 07:22
  • There's at least two questions using JavaScript to convert numbers into words. https://stackoverflow.com/q/14766951/5675325 and https://stackoverflow.com/q/5529934/5675325 – Tiago Martins Peres Oct 26 '19 at 07:22
  • 1
    @Rodney Just have your `toWordsOrdinal` have its second argument take the digits you want to translate. If you want to include the `st`, etc as well, then there's no need for the capturing group, and you can use the first argument instead – CertainPerformance Oct 26 '19 at 07:24
  • @Tiago Martins Peres Yes I already have the function to convert the numbers to words. I am trying to capture the entire string that contains the search substring so that I can pass it to that function. – Rodney Oct 26 '19 at 07:25
  • 1
    @Rodney Then just use the first parameter of the `.replace` callback – CertainPerformance Oct 26 '19 at 07:26
  • @CertainPerformance Using your function, is there a way I could just access the results as a variable instead of doing the replace() ? – Rodney Oct 27 '19 at 02:47
  • 1
    @Rodney If you don't want to replace the string, you can use `match` instead, to get an array of matching substrings. Then iterate through them and pass them to `toWordsOrdinal`. and do whatever you want with the result. Eg `for (const substr of this.textContent.match(/\d+(?:st|nd|rd|th)\b/)) { const result = translateDigits(substr); }` – CertainPerformance Oct 27 '19 at 03:32
0

$("div.dirInstruction").each(function() {
  if ($(this).text().indexOf("1st") >= 0) {
    var new_word = $(this).text().replace(/1st/g, "one hundred first");
    $(this).text(new_word);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="dirInstruction">101st</div>
<div class="dirInstruction">1000001st</div>
<div class="dirInstruction">1st</div>
<div class="dirInstruction">addasd1stbbb</div>
<div class="dirInstruction">1st1st1st</div>

Replace with a regular expression.

sugars
  • 1,473
  • 7
  • 17
  • Sorry, I updated my question with the scenario to clarify why I am needing to find the entire string the substring occurs in. – Rodney Oct 26 '19 at 06:51
0

You know beforehand the content present in dirInstructions and you mention to know how to convert from number into word (There's at least two questions using JavaScript to convert numbers into words as well Convert digits into words with JavaScript and JavaScript numbers to Words)

So, i suggest the following steps

  1. Create a JavaScript array from the content present in the divs.
  2. Create a JavaScript function that takes two arguments - the user's input and the array created in Step 1.

Autocompletion isn't something new and a working example can be found in W3schools.

Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145