From: Captain Obvious on
R> IMHO a better way to approach this, particular for beginners, is to use
R> abstract associative maps rather than association lists. A CL
R> implementation of abstract associative maps can be found here:

What's wrong with hash-tables which are in the standard?

R> (defun count-items (list)
R> (let ((c (make-instance 'counter)))
R> (dolist (item list) (add c item))
R> c))

(defun count-items (list)
(let ((ht (make-hash-table)))
(dolist (item list)
(incf (gethash item ht 0)))
ht))

The only difference I see is that GETHASH accessor has default value and you
can use INCF directly on it, no need for a goddamn additional function for
that.

From: Tim Bradshaw on
On 2010-06-18 14:11:55 +0100, Pascal J. Bourguignon said:

> I think it's explained by the + after compound-form: it allows for
> several forms to be executed in sequence in the finally clause.

But if it allowed an unconditional there that would still be OK, you'd
just need to say "finally do ... ..." since DO takes a compoint-form+
as well.

This annoys me fairly frequently, I can't see a good reason for it.

From: refun on
In article <87vfr3Ft2dU1(a)mid.individual.net>, eric(a)boese-wolf.eu says...
>
> Hello there!
>
> I'm starting to learn lisp and doing the exercises of Ansi Common Lisp
> authored by Paul Graham.
>
> So my solution to counting occurences in a list and outputting a
> list of dotted pairs (symbol . count) sorted by count is
>
> (defun occurences-helper (lst result)
> (if (null lst)
> result
> (progn
> (let ((symb (car lst)))
> (let ((test (assoc symb result)))
> (if test
> (setf (cdr test) (+ (cdr test) 1))
> (setf result (cons (cons symb 1) result)))))
> (occurences-helper (cdr lst) result))))
>
> (defun occurences (lst)
> (sort
> (occurences-helper lst ())
> #'(lambda (x y)
> (>
> (cdr x)
> (cdr y))))
> )
>
>
> And I thought: "Hmm that doesn't look elegant" but I'm not used to
> recursion and functional programming and that stuff so I didn't
> came up with a better version.
>
> Maybe some experienced lisp hacker may provide a different one?
>
> Yours sincerely,
>
> Eric

Here's another hashtable-based solution:

First, a function to convert a hashtable to an alist:

(defun hashtable->alist (ht &aux alist)
(maphash #'(lambda (key value) (push (cons key value) alist)) ht)
(nreverse alist))

or with LOOP:

(defun hashtable->alist (ht)
(loop for key being the hash-keys in ht using (hash-value value)
collect (cons key value)))

The actual COUNT-OCCURANCES function:

(defun count-occurances (list &aux (ht (make-hash-table)))
(dolist (element list (sort (hashtable->alist ht) #'> :key #'cdr))
(incf (gethash element ht 0))))
From: Pascal Costanza on
On 18/06/2010 09:19, Nicolas Neuss wrote:
> "Frode V. Fjeld"<frode(a)netfonds.no> writes:
>
>> (defun occurences-helper (list)
>> (loop with result = nil
>> for element in list
>> do (incf (getf result element))
>> finally (return result)))
>
> Small correction: (getf result element 0)

Two functional versions (just out of curiosity):

(defun count-elements (sequence &key (test #'eql))
(reduce (lambda (element result)
(acons element
(let ((cons (assoc element result :test test)))
(if cons (1+ (cdr cons)) 1))
(remove element result :key #'car :test test)))
sequence :initial-value '() :from-end t))


(defun count-elements/2 (sequence)
(reduce (lambda (element result)
(multiple-value-bind
(indicator value tail)
(get-properties result (list element))
(if indicator
(list* element (1+ value)
(nconc (ldiff result tail) (cddr tail)))
(list* element 1 result))))
sequence :initial-value '() :from-end t))

I used :from-end to keep the elements in the order they appear in the
original sequences.


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Frode V. Fjeld on
Nicolas Neuss <lastname(a)kit.edu> writes:

> "Frode V. Fjeld" <frode(a)netfonds.no> writes:
>
>> (defun occurences-helper (list)
>> (loop with result = nil
>> for element in list
>> do (incf (getf result element))
>> finally (return result)))
>
> Small correction: (getf result element 0)

Thanks, I guess I forgot to qualify all my code as "untested".

--
Frode V. Fjeld