title: How to delete all numbers from a string?
body: <p>Below is an example of a test case:</p>
  <pre class="lang-python prettyprint-override"><code>inpoot = &quot;A.p.p.l.e (45) Orange (5.11) Kiwi&quot;  # WE HAVE
  outpoot = &quot;A.p.p.l.e () Orange () Kiwi&quot; # WE WANT
  </code></pre>
  <p>The only reason I spelled <code>inpoot</code> incorrectly is  because <code>input</code> is a reserved language keyword.</p>
  <p>One might think that the following would work:</p>
  <pre class="lang-python prettyprint-override"><code>import string
  def kill_numbers(text: str) -&gt; str:
      text = str(text)
      return &quot;&quot;.join(filter(lambda ch: ch not in string.digits, text))
  </code></pre>
  <p>However, the decimal point (<code>.</code>) in a decimal numbers will be preserved.</p>
  <pre class="lang-python prettyprint-override"><code>inpoot = &quot;A.p.p.l.e (45) Orange T5.11T Kiwi 99 Apricot&quot;
  
  outpoot = kill_numbers(inpoot)
  print(repr(outpoot))
  
  # prints 'A.p.p.l.e  () Orange T.T Kiwi'
  # We want `TT` not `T.T`
  # the output contains a stray decimal point. 
  
  outpoot = kill_numbers(&quot;Strawberry 3.145 Plum&quot;)
  print(repr(outpoot))
  
  # fails to delete the `.` in `3.145`
  </code></pre>
  <div class="s-table-container">
  <table class="s-table">
  <thead>
  <tr>
  <th>INPUT</th>
  <th>BAD OUTPUT</th>
  <th>DESIRED OUTPUT</th>
  </tr>
  </thead>
  <tbody>
  <tr>
  <td><code>&quot;3.14&quot;</code></td>
  <td><code>&quot;.&quot;</code></td>
  <td><code>&quot;&quot;</code> (empty string)</td>
  </tr>
  </tbody>
  </table>
  </div>
  <p>So, how can we delete all numbers, including decimal numbers?</p>
  <p>A substitution using regular expressions is theoretically possible.</p>
  <pre class="lang-python prettyprint-override"><code>import re
  test_case =  &quot;(.4) A.p.p.l.e (44) Orange .... (4.44) Kiwi . . . . .&quot;
  result = re.sub(&quot;[0-9]+\.?[0-9]*|\.[0-9]+&quot;, &quot;&quot;, test_case)
  print(result) # () A.p.p.l.e () Orange .... () Kiwi . . . . .
  </code></pre>
  <p>The regular expression shown above works for that one test case, but not all test cases.</p>
  <p>The table below shows how various regular expressions perform on various test inputs.</p>
  <p><strong>KEY FOR TABLE</strong></p>
  <ul>
  <li><code>-</code> means that the regex does <em>NOT</em> match the string</li>
  <li><code>+</code> means that the regex matches the entire string</li>
  <li><code>meh</code> means that the regex matches a small part of string, but not the whole thing.</li>
  </ul>
  <div class="s-table-container">
  <table class="s-table">
  <thead>
  <tr>
  <th>REGEX</th>
  <th><code>' 1  '</code></th>
  <th><code>'2'</code></th>
  <th><code>'3'</code></th>
  <th><code>'365'</code></th>
  <th><code>'9.43'</code></th>
  <th><code>'-5000'</code></th>
  <th><code>'+10'</code></th>
  <th><code>'3.10.4'</code></th>
  <th><code>'0001'</code></th>
  <th><code>'.5'</code></th>
  <th><code>'.'</code></th>
  <th><code>'591.'</code></th>
  <th><code>''</code></th>
  <th><code>'0x77F'</code></th>
  <th><code>'3.456e11'</code></th>
  </tr>
  </thead>
  <tbody>
  <tr>
  <td><code>[0-9]+\\.?[0-9]*|\\.[0-9]+</code></td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>-</td>
  <td>-</td>
  <td>+</td>
  <td>-</td>
  <td>+</td>
  <td>meh</td>
  <td>meh</td>
  </tr>
  <tr>
  <td><code>[+-]?[0-9]+\\.?[0-9]*|\\.[0-9]+</code></td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>-</td>
  <td>-</td>
  <td>+</td>
  <td>-</td>
  <td>+</td>
  <td>meh</td>
  <td>meh</td>
  </tr>
  <tr>
  <td><code>[+-]?([0-9]+\\.?[0-9]*|\\.[0-9]+)</code></td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>-</td>
  <td>-</td>
  <td>+</td>
  <td>-</td>
  <td>+</td>
  <td>meh</td>
  <td>meh</td>
  </tr>
  <tr>
  <td><code>[0-9]*\\.?[0-9]*</code></td>
  <td>meh</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  </tr>
  <tr>
  <td><code>[0-9]+\\.?[0-9]+</code></td>
  <td>+</td>
  <td>+</td>
  <td>+</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>-</td>
  <td>+</td>
  <td>+</td>
  <td>meh</td>
  <td>+</td>
  <td>meh</td>
  <td>meh</td>
  </tr>
  <tr>
  <td><code>[0-9]+\\.?[0-9]*</code></td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>-</td>
  <td>meh</td>
  <td>+</td>
  <td>-</td>
  <td>+</td>
  <td>meh</td>
  <td>meh</td>
  </tr>
  <tr>
  <td><code>[0-9]*\\.?[0-9]+</code></td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>-</td>
  <td>-</td>
  <td>+</td>
  <td>meh</td>
  <td>+</td>
  <td>meh</td>
  <td>meh</td>
  </tr>
  <tr>
  <td><code>\\d+</code></td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>-</td>
  <td>meh</td>
  <td>+</td>
  <td>meh</td>
  <td>+</td>
  <td>meh</td>
  <td>meh</td>
  </tr>
  <tr>
  <td><code>[0-9]</code></td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>+</td>
  <td>meh</td>
  <td>+</td>
  <td>meh</td>
  <td>meh</td>
  </tr>
  <tr>
  <td><code>\\d</code></td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>+</td>
  <td>meh</td>
  <td>+</td>
  <td>meh</td>
  <td>meh</td>
  </tr>
  <tr>
  <td><code>\\d*</code></td>
  <td>meh</td>
  <td>-</td>
  <td>-</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  <td>meh</td>
  <td>-</td>
  <td>meh</td>
  <td>meh</td>
  </tr>
  </tbody>
  </table>
  </div>
  <p>The same table in ASCII form might be easier to read and understand:</p>
  <pre class="lang-none prettyprint-override"><code>                                ' 1  ' '2' '3' '365' '9.43' '-5000' '+10' '3.10.4' '0001' '.5'  '.' '591.' '' '0x77F' '3.456e11'
  [0-9]+\.?[0-9]*|\.[0-9]+             -   -   -     -      -     meh   meh      meh      -    -    +      -  +     meh        meh
  [+-]?[0-9]+\.?[0-9]*|\.[0-9]+        -   -   -     -      -       -     -      meh      -    -    +      -  +     meh        meh
  [+-]?([0-9]+\.?[0-9]*|\.[0-9]+)      -   -   -     -      -       -     -      meh      -    -    +      -  +     meh        meh
  [0-9]*\.?[0-9]*                    meh   -   -     -      -     meh   meh      meh      -    -    -      -  -     meh        meh
  [0-9]+\.?[0-9]+                      +   +   +     -      -     meh   meh      meh      -    +    +    meh  +     meh        meh
  [0-9]+\.?[0-9]*                      -   -   -     -      -     meh   meh      meh      -  meh    +      -  +     meh        meh
  [0-9]*\.?[0-9]+                      -   -   -     -      -     meh   meh      meh      -    -    +    meh  +     meh        meh
  \d+                                  -   -   -     -    meh     meh   meh      meh      -  meh    +    meh  +     meh        meh
  [0-9]                                -   -   -   meh    meh     meh   meh      meh    meh  meh    +    meh  +     meh        meh
  \d                                   -   -   -   meh    meh     meh   meh      meh    meh  meh    +    meh  +     meh        meh
  \d*                                meh   -   -     -    meh     meh   meh      meh      -  meh  meh    meh  -     meh        meh
  </code></pre>
  <p>In my humble opinion, regular expressions are a nightmare.</p>
  <p>To digress, it took me a long time to realize that:</p>
  <pre class="lang-none prettyprint-override"><code>IMHO = In my humble opinion`. I don't speak acronym very well. 
  </code></pre>
  <p>Back to business...</p>
  <p>I cannot find a regex which satisfies the following requirements:</p>
  <ul>
  <li>the regex must <em><strong>not</strong></em> match the empty string (<code>&quot;&quot;</code>)</li>
  <li>the regex must <em><strong>not</strong></em> match any sub-string of a version number, such as <code>&quot;3.10.4&quot;</code> At most one decimal point is allowed to appear in what we call a &quot;number&quot;</li>
  <li>the regex must <em><strong>not</strong></em> match free-floating decimal points (<code>&quot;.&quot;</code>).</li>
  </ul>
  <p>Desired behavior is as follows:</p>
  <div class="s-table-container">
  <table class="s-table">
  <thead>
  <tr>
  <th>PSEUDO-NUMBER</th>
  <th><code>IS_A_NUMBER()</code></th>
  <th>NOTES</th>
  </tr>
  </thead>
  <tbody>
  <tr>
  <td><code>&quot;1&quot;</code></td>
  <td>Yes</td>
  <td>int</td>
  </tr>
  <tr>
  <td><code>&quot;2&quot;</code></td>
  <td>Yes</td>
  <td>int</td>
  </tr>
  <tr>
  <td><code>&quot;365&quot;</code></td>
  <td>Yes</td>
  <td>int</td>
  </tr>
  <tr>
  <td><code>&quot;365.&quot;</code></td>
  <td>No</td>
  <td><code>365.</code> is a float equivalent to <code>365.0</code> However, I do not want to delete the (<code>.</code>) at the end of the string <code>&quot;The number of houses was 44.&quot;</code></td>
  </tr>
  <tr>
  <td><code>&quot;9.43&quot;</code></td>
  <td>Yes</td>
  <td>one decimal points</td>
  </tr>
  <tr>
  <td><code>&quot;-5000&quot;</code></td>
  <td>Yes</td>
  <td></td>
  </tr>
  <tr>
  <td><code>&quot;+10&quot;</code></td>
  <td>Yes</td>
  <td></td>
  </tr>
  <tr>
  <td><code>&quot;0001&quot;</code></td>
  <td>Yes</td>
  <td></td>
  </tr>
  <tr>
  <td><code>&quot;.5&quot;</code></td>
  <td>Yes</td>
  <td><code>.5</code> is equivalent to <code>0.5</code></td>
  </tr>
  <tr>
  <td><code>&quot;1&quot;</code></td>
  <td>Yes</td>
  <td></td>
  </tr>
  <tr>
  <td><code>&quot;0x77F&quot;</code></td>
  <td>Yes</td>
  <td></td>
  </tr>
  <tr>
  <td><code>&quot;3.456e11&quot;</code></td>
  <td>Yes</td>
  <td>pseudo-scientific-notation</td>
  </tr>
  <tr>
  <td><code>&quot;3.10.4&quot;</code></td>
  <td><strong>Not</strong> a number</td>
  <td>two decimals points</td>
  </tr>
  <tr>
  <td><code>&quot;.&quot;</code></td>
  <td><strong>Not</strong> a number</td>
  <td></td>
  </tr>
  <tr>
  <td><code>&quot;&quot;</code></td>
  <td><strong>Not</strong> a number</td>
  <td>do not match the empty string</td>
  </tr>
  </tbody>
  </table>
  </div><hr />
  <h1>EDIT:</h1>
  <p>The following are defined to be <em>seed numbers</em> ...</p>
  <p>(<code>1</code>, <code>365</code>, <code>9.43</code>, <code>-5000</code>, <code>+10</code>, <code>0001</code>, <code>.5</code>, <code>.5</code>, <code>0x77F</code>, <code>3.456e11</code>)</p>
  <p>A <em>valid number</em> is defined to be any <em>seed number</em> or a string formed by a <em>seed number</em> by doing one of the following:</p>
  <ol>
  <li>Iteratively replacing any digit in a <em>seed number</em> with <code>99</code></li>
  <li>Replacing any digit in a <em>valid number</em> with a different digit.</li>
  <li>Replacing <code>F</code> in <code>0xF</code> with <code>2F</code> or <code>F2</code> or <code>A</code>,<code>B</code>,<code>C</code> ,<code>D</code>, or <code>E</code>.</li>
  </ol>
  <p>For example, you could replace the <code>5</code> in <code>-5000</code> with <code>9</code> to get <code>-9000</code></p>
  <p>Also, you could replace the <code>5</code> in <code>.5</code> with <code>99</code> to get <code>.99</code></p>
  <p>The above defines language <strong>L</strong>.</p>
  <p>My question could be re-worded as follows:</p>
  <p>What algorithm <strong>A</strong> will return <em><strong>s′</strong></em> from input string <em><strong>s</strong></em> such that:</p>
  <ul>
  <li><em><strong>s</strong></em> is any finite-length string of ASCII characters.</li>
  <li>string <em><strong>s′</strong></em> is like string <em><strong>s</strong></em> except that all maximal substrings of <em><strong>s</strong></em> which are in language <strong>L</strong>, have been replaced by empty strings.</li>
  </ul>
  <p>A substring <strong>t</strong> of string <strong>s</strong> is maximal and <strong>t</strong> is in language <strong>L</strong> if it is not possible to tack on one more character to the left or to the right of <strong>t</strong> to form <strong>t′</strong>, such that <strong>t′</strong> is a string in language <strong>L</strong> and <strong>t′</strong> is a substring of <strong>s</strong>.</p>
  <p>In layman's terms, if you see &quot;apple 12.345&quot; you should go after &quot;12.345&quot; not &quot;2.34&quot;.</p>
  <p>Indices matter. Sometimes, it makes no sense to say that the letter <code>&quot;a&quot;</code> is a sub-string of <code>&quot;abracadabra&quot;</code>. Which letter &quot;a&quot; is it? It it the letter &quot;a&quot; third-from-the-left, or second-from-the left?</p>
  <p>We define a <em><strong>string</strong></em> to a mathematical mapping <strong>M</strong> from a finite subset of the natural numbers to the ASCii character set such that the absolute difference between the maximum of the domain of mapping <strong>M</strong> and the minimum of the domain of mapping <strong>M</strong> is the sum of one and the cardinality of the domain of mapping <strong>M</strong>.</p>
  <p>For any string <strong>SML</strong> and any string <strong>LRG</strong>, we say that <strong>SML</strong> is a sub-string of <em><strong>LRG</strong></em> if and only if <strong>SML[k]</strong> = <strong>LRG[k]</strong> for all <strong>k</strong> in the domain of <em>string</em> <strong>SML</strong></p>
  <h1>END OF EDIT</h1>