8

How can I sum a set of numbers interspersed with text in the region (not a rectangular region). For example, if the region contains this text:

Widgets 234
Sprockets 44
Nubbins 12
Fork handles 4
4 Candles

I'm looking for a command that will report 298 somehow (298 = 234 + 44 + 12 + 4 + 4) -- I guess either by echoing that to the message area or inserting it in the buffer.

Ideally it would cope with both integers and floating point numbers.

1
  • 1
    Examples are clearly missing "Ronnies 2" :)
    – phils
    Apr 27, 2015 at 10:45

4 Answers 4

6

Here's one:

(require 'cl-lib)
(defun sum-numbers-in-region (start end)
  (interactive "r")
  (message "%s"
           (cl-reduce #'+
                      (split-string (buffer-substring start
                                                      end))
                      :key #'string-to-number)))

Because it uses string-to-number, it will treat the the token "1hello" as the number "1", but won't treat "hello2" as a number. It also works with decimals (e.g., 2.4).

5

Specifically for your case, assuming this is the entire text of the buffer:

  1. M-xreplace-regexpRET[^0-9]+RET+RET
  2. C-x h - select all.
  3. C-x * e (make sure there is no trailing plus sign).
2
  • The replace me with a trailing + at the end of the line which calc-mode didn't like: it worked when I removed that. Interesting answer though a bit inconvenient for this simple use case. Apr 26, 2015 at 21:50
  • 4
    Another calc solution: mark region, C-x * g to grab, V u (calc-unpack), then tap + until you've summed all the numbers.
    – nanny
    Apr 27, 2015 at 13:12
2

I don't know of a built-in command that does this, but you could make your own:

(defun sum-region-nums (beg end)
  (interactive "r")
  (save-excursion
    (goto-char beg)
    (let (nums total)
      (while (re-search-forward "\\b[0-9]+\\(\\.[0-9]+\\)*\\b" end t)
        (push (string-to-number (match-string-no-properties 0))
              nums))
      (setq total (apply #'+ nums))
      (message "%s" total)
      total)))
1
  • @zck's answer is nicer (as long as you're ok with the number being part of the word). The regexp in this answer would need to be extended to support negative numbers.
    – Kyle Meyer
    Apr 26, 2015 at 20:04
2

If you have a region that contains a formula:

234+44+12+4+4

You can mark the region and run C-x * g to evaluate in a new buffer.

(calc-dispatch-help ARG)
For moving data into and out of Calc:

  G  calc-grab-region.  Grab the region defined by mark and point into Calc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.