From: Lowell
Subject: Counting occurences of an item in a list: is there a better way?
Date: 
Message-ID: <bk3kgk$9s$1@mughi.cs.ubc.ca>
To count the occurences of the number h in a list, I have the following:

(let ((result 0))
   (loop for i in finals
         do (when (= i h)
              (incf result)))
   result))

Is there already something built in to CL that does something similar? 
Or is there a better (or more abstract) way I should be doing this?

--

Lowell

From: Peter Seibel
Subject: Re: Counting occurences of an item in a list: is there a better way?
Date: 
Message-ID: <m3ad96bmcy.fsf@javamonkey.com>
Lowell <······@cs.ubc.ca> writes:

> To count the occurences of the number h in a list, I have the following:
> 
> (let ((result 0))
>    (loop for i in finals
>          do (when (= i h)
>               (incf result)))
>    result))
> 
> Is there already something built in to CL that does something similar?
> Or is there a better (or more abstract) way I should be doing this?

  (count h finals :test #'=)

Or if you really want to use loop (as you might if you wanted to count
more than one thing at a time) you can write:

 (loop for i in finals counting (= i h))

As an example of counting more than one thing at a time you might write something like:

  (loop for i in finals
    counting (= i h1) into h1s
    counting (= i h2) into h2s
    finally (return (list h1s h2s)))

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Jock Cooper
Subject: Re: Counting occurences of an item in a list: is there a better way?
Date: 
Message-ID: <m365ju2cb1.fsf@jcooper02.sagepub.com>
Peter Seibel <·····@javamonkey.com> writes:

> Lowell <······@cs.ubc.ca> writes:
> 
> > To count the occurences of the number h in a list, I have the following:
> > 
> > (let ((result 0))
> >    (loop for i in finals
> >          do (when (= i h)
> >               (incf result)))
> >    result))
> > 
> > Is there already something built in to CL that does something similar?
> > Or is there a better (or more abstract) way I should be doing this?
> 
>   (count h finals :test #'=)
> 
> Or if you really want to use loop (as you might if you wanted to count
> more than one thing at a time) you can write:
> 
>  (loop for i in finals counting (= i h))
> 
> As an example of counting more than one thing at a time you might write 
>something like:
> 
>   (loop for i in finals
>     counting (= i h1) into h1s
>     counting (= i h2) into h2s
>     finally (return (list h1s h2s)))
> 

Ob Recursive version:

(labels ((r-count (list count)
           (if list
               (r-count (cdr list) (if (= (car list) test-value) 
                                       (1+ count) 
                                       count))
               count)))
   (r-count <the-list> 0))

using appropriate test function and value 
                                       
From: Anton van Straaten
Subject: Re: Counting occurences of an item in a list: is there a better way?
Date: 
Message-ID: <zEn9b.15338$NM1.11968@newsread2.news.atl.earthlink.net>
Jock Cooper wrote:
> Ob Recursive version:
>
> (labels ((r-count (list count)
>            (if list
>                (r-count (cdr list) (if (= (car list) test-value)
>                                        (1+ count)
>                                        count))
>                count)))
>    (r-count <the-list> 0))
>
> using appropriate test function and value

In that case, we need the ObRecursionAbstractedOut version:

  (reduce
    (lambda (count x)
      (if (= x test-value) (1+ count) count))
    <the-list>
    :initial-value 0)
From: Mark Hurd
Subject: Re: Counting occurences of an item in a list: is there a better way?
Date: 
Message-ID: <3f68826f_1@news.iprimus.com.au>
Anton van Straaten wrote:
> Jock Cooper wrote:
> > Ob Recursive version:
> >
> > (labels ((r-count (list count)
> >            (if list
> >                (r-count (cdr list) (if (= (car list) test-value)
> >                                        (1+ count)
> >                                        count))
> >                count)))
> >    (r-count <the-list> 0))
> >
> > using appropriate test function and value
>
> In that case, we need the ObRecursionAbstractedOut version:
>
>   (reduce
>     (lambda (count x)
>       (if (= x test-value) (1+ count) count))
>     <the-list>
>     :initial-value 0)

Which leads to:

(reduce + (mapcar
 (lambda (x)
  (if (= x test-value) 1 0))
 <the-list>
 :initial-value 0)

[Or:

(apply + (cons 0 (mapcar
 (lambda (x)
  (if (= x test-value) 1 0))
 <the-list>)))

]

But this is just a filter:

(reduce + (mapcan
 (lambda (x)
  (when (= x test-value) '(1))
 <the-list>)
 :initial-value 0)

Or

(let ((count 0))
 (mapc
  (lambda (x)
   (when (= x test-value)
    (++ count))
 <the-list>)
  count)

Which leads to the other loops suggested earlier in this thread.

-- 
Regards,
Mark Hurd, B.Sc.(Ma.) (Hons.)

PS I use DotLisp regularly which has a syntax with some extraneous brackets
removed and much of CL not present, so if I've not successfully made the above
valid CL, please don't flame me too much. I have tried to get it right, except
I haven't used #' anywhere because the previous post didn't... oh, and it
hasn't been tested...
From: Lowell
Subject: Re: Counting occurences of an item in a list: is there a better way?
Date: 
Message-ID: <bk5nlh$bqj$1@mughi.cs.ubc.ca>
Thanks. That's exactly what I was looking for :-)

Peter Seibel wrote:

> Lowell <······@cs.ubc.ca> writes:
> 
> 
>>To count the occurences of the number h in a list, I have the following:
>>
>>(let ((result 0))
>>   (loop for i in finals
>>         do (when (= i h)
>>              (incf result)))
>>   result))
>>
>>Is there already something built in to CL that does something similar?
>>Or is there a better (or more abstract) way I should be doing this?
> 
> 
>   (count h finals :test #'=)
> 
> Or if you really want to use loop (as you might if you wanted to count
> more than one thing at a time) you can write:
> 
>  (loop for i in finals counting (= i h))
> 
> As an example of counting more than one thing at a time you might write something like:
> 
>   (loop for i in finals
>     counting (= i h1) into h1s
>     counting (= i h2) into h2s
>     finally (return (list h1s h2s)))
> 
> -Peter
>