``` Subject: Re: Basic List processing From: rpw3@rpw3.org (Rob Warnock) Date: Mon, 10 Nov 2008 05:01:45 -0600 Newsgroups: comp.lang.lisp Message-ID: <g_6dnZ55oIQEiYXUnZ2dnUVZ_g6dnZ2d@speakeasy.net> ```
```Mark Carter <me@privacy.net> wrote:
+---------------
| Suppose I have: (defvar *list* '((1 2) (3 4) (5 6) (1 7)))
| Now, suppose I want the "keys" of the list, defined by the first element
| of the list. Is there a Lisp function which is callable something like:
| (keys *list* :key #'first) ; => '(1 3 5)
+---------------

Uh... What's wrong with just (MAPCAR #'FIRST *LIST*)?
[Oh, and your example output is wrong...]

+---------------
| Suppose further that I want to accumulate totals based on keys. The
| first element in the list is the key, and the second element in the list
| is the value. Is there a Lisp function which is callable something like:
| (accum *list*) ; => '( (1 9) (3 4) (5 6) )
+---------------

If the lists were really, *really* big, with lots of duplicate keys,
I'd probably use a hash table to store keys & sums. Otherwise I'd just
use a dumb, simple, N^2 cost insertion sum. You know, something like this:

> (defun accum-by-key (list)
(loop with result = nil
for (first second) in list
do (let ((found (find first result :key #'first)))
(if found
(incf (second found) second)
(push (list first second) result)))
finally (return (reverse result))))

ACCUM-BY-KEY
> (accum-by-key *list*)

((1 9) (3 4) (5 6))
>

-Rob

p.s. I would have used a WHEN (FIND...) (INCF (SECOND IT) SECOND) ELSE...
except that IT can *only* be used in RETURN or accumulation clauses
(COLLECT, SUM, etc.). (*sigh*)

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607

```