# Sorting counts in descending order

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))

``````
• `C-h f sort` tells you how to sort a list, using a predicate of your choice. 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? Mar 22 at 21:27
• The elaboration is enough.
– Veak
Mar 23 at 0:09

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.