1

Have the following code that counts the number of times words are used. I want to list the results sorted by the number of counts.


    (defun rk-word-analysis (reg-beg reg-end)
      "Count times words are used in a region, ignoring punctuation."
    
      (interactive "r")
    
      (let ($words)
    
        (save-excursion
          (goto-char reg-beg)
          (while (re-search-forward "\\w+" reg-end t)
        (let* (($word (intern (match-string 0)))
               ($cell (assq $word $words)))
          (if $cell
              (setcdr $cell (1+ (cdr $cell)))
            (setq $words (cons (cons $word 1) $words))))))
        (when (interactive-p)
          (message "%S" $words))
    
        $words))

4
  • 1
    C-h f sort tells you how to sort a list, using a predicate of your choice.
    – NickD
    Mar 21 at 2:18
  • I need some elaboration for sorting the $words list. Gone with (sort $words '<), which gets sort to complain with sort: Wrong type argument: number-or-marker-p, (This . 1)
    – Veak
    Mar 21 at 2:29
  • Was the elaboration in the answer enough?
    – NickD
    Mar 22 at 21:27
  • The elaboration is enough.
    – Veak
    Mar 23 at 0:09

1 Answer 1

1

Use the sort function with the appropriate predicate. Since the list that you want to sort is a list of pairs, (word . count), you cannot compare using < which can only compare numbers: (< '("foo" . 3) '("bar" . 7)) does not work because < cannot compare pairs. Since you want to sort the list by increasing order of the count, you have to select the count part to compare. So the appropriate predicate would be:

(lambda (x y) (< (cdr x) (cdr y))

In other words, to compare x and y, you take the cdr of each (i.e. the count part of the pair) and compare them with < - this works since you are comparing numbers.

Here's an example of how to call sort:

;; initialize $words
(setq $words '(("foo" . 5) ("bar" . 3) ("baz" . 4)))
(("foo" . 5) ("bar" . 3) ("baz" . 4))

;; sort the list according to the predicate
(setq sorted-list (sort $words (lambda (x y) (< (cdr x) (cdr y)))))
(("bar" . 3) ("baz" . 4) ("foo" . 5))

;; how the sorted list looks
sorted-list
(("bar" . 3) ("baz" . 4) ("foo" . 5))

EDIT: This is obviously ascending order. For descending order, replace < with > in the predicate.

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.