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