as.bemerguy
as.bemerguy

Reputation: 3

Count elements and return them

I want to count the elements in a list and return a list containing the elements paired with them respective quantity

Something like that:

Input: (count-elements '(a b d d a b c c b d d))

Output: ((a 2) (b 3) (d 4) (c 2))

How can I do it? I'm not having any success trying to pair the element and its accounting

Upvotes: 0

Views: 128

Answers (1)

Mooncrater
Mooncrater

Reputation: 4861

Your problem can be divided into three broad parts:

  1. Duplicate recognition/ deletion : This can be done by either removing all the duplicates of every element, or by knowing that the current element is a duplicate(and thus not counting it as a new element.). This(the former strategy) can be done by using the function remove-duplicates
  2. Counting: A way to actually count the elements. This can be done by the function count
  3. Combination: A way to combine the results into a list. This can be done by the macro push.

The Code:

(defun count-elements (lst)
  (loop for i in (remove-duplicates lst)
        with ans = nil
        do (push (list i (count i lst)) ans)
        finally (return ans)))

CL-USER> (count-elements '(a a b c))
((C 1) (B 1) (A 2))
CL-USER> (count-elements '(a b c d d a b s a c d))
((D 3) (C 2) (A 3) (S 1) (B 2))
CL-USER> 

NOTE: The result might not be arranged as you would expect, because of the value returned by remove-duplicates


EDIT: As pointed out by coredump, a better version of count-elements would be:

(defun count-elements (lst)
  (map 'list
       (lambda (e)
         (list e (count e lst)))
       (remove-duplicates lst)))

which, instead of using loop, uses map.

Upvotes: 1

Related Questions