2

The following function fails to return "16":

(string-to-number "bm16")

It seems to get tripped up if the first characters of a string aren't numbers. Is there a way to construct an elisp function which takes a string of text and returns the number it contains (it doesn't have to handle decimals)?

George
  • 919
  • 5
  • 17
  • There is no function named first-number-from-string in my emacs: how is it defined? where did you get it from? – NickD Mar 17 '21 at 05:00
  • NickD: My mistake. I meant string-to-number. – George Mar 17 '21 at 05:22
  • What should happen for the string "abcdef" which contains no digits? And do you want the result to be a number or its string representation? – NickD Mar 17 '21 at 05:27

2 Answers2

2

A possible implementation: find the first digit, get the substring of the original string that starts at that first digit and then call string-to-number on the result:

(defun first-number-of-string (s)
  (string-to-number (substring s (string-match-p "[0-9]" s))))

(first-number-of-string "bm16" -> 16 (first-number-of-string "abc123def456" -> 123 (first-number-of-string "abc123") -> 123 (first-number-of-string "123def") -> 123 (first-number-of-string "123") -> 123 (first-number-of-string "abcdef") -> 0

That's assuming that the answers to the questions in my comment are that you indeed want a number, not its string representation, and in the case where there is no number in the string, having the function return 0 is acceptable.

Drew
  • 77,472
  • 10
  • 114
  • 243
NickD
  • 29,717
  • 3
  • 27
  • 44
1

An alternative using cl functions:

(defun first-number-in-string(s)
   (string-to-number
     (seq-take-while
     #'cl-digit-char-p 
     (seq-drop-while
      (lambda(x)(not (cl-digit-char-p x)))
      s))))
(mapcar #'first-number-in-string 

'( "bm16" "abc123def456" "abc123" "123def" "123" "abcdef")) => (16 123 123 123 123 0)

The same algorithm splitted for clarity::

(defun collect-first (pred coll)
  (seq-take-while pred
                  (seq-drop-while (lambda (x) (not(funcall pred x)))
                                  coll)))

(defun first-number-in-string(s) (string-to-number (collect-first #'cl-digit-char-p s)))

gigiair
  • 2,166
  • 1
  • 9
  • 15