What's a more concise way to count the number of times an element occurs in a list in J?

Tag: j Author: woainiyd Date: 2010-09-10

Here's the (probably naive) way I've done it:

count =: 4 : '# (#~ =&x) y'"1 0 1

In other words, if I say 4 count 3 4 4 3 4 7 9 the result is 3, because 4 occurs 3 three times in the given list.

This works perfectly, but I wonder whether J offers some more concise way to phrase this.

Best Answer

When I do this, knowing that I'm only ever going to have a list and not a matrix, I use:

count =: 4 : '+/x=y'

Or for multiple searches in the list:

count =: 4 : '+/x=y'"0 1

Your method copies over only the elements that are equal to x, then counts the result. Summing the ones for equality is one less operation.

comments:

As always from you, an insightful answer. Thanks again!
Not a problem, I'm just glad I could help.

Other Answer1

I agree with the algorithm provided by MPelletier. Since you're asking for concision, tacit phrasings may be worth looking at. Here's one such program, assigned to a name:

count =: +/ @: =

It can also be used as an anonymous verb, as in this example:

   4 (+/ @: =) 3 4 4 3 4 7 9
3

A synonym is [: +/ =

As MPelletier said, this algorithm works when what you want to count are atoms in a simple list. (A similar need that would require a different approach would be counting matrices matched in a list of similarly-shaped matrices.)

comments:

Yeah, once MPelletier had provided my with the algorithm, I did turn it into its tacit form. (I used the @: variant rather than the capped one.) I created a verb called counts which in its dyadic form is basically +/ @: = "0 1 and in its monadic form returns a two-column matrix which counts the given list.
In other words, the monadic form of counts is (, count&y)"0 ~. /:~ y.
I think a monadic verb that tallies for the nub should be kept minimalistic: [: +/"1 = seems the "classic" calculation of this. If you want to do sorting, or joining to the nub, fine, but I recommend you don't mix those into the "main" verb.
Thanks @kaleidic, I usually go for the simplest, direct form and forget to make it tacit. My understanding of the @, @., and @: adverbs is seriously lacking.

Other Answer2

We should probably also mention Member of Interval E.:

4 E. 3 4 4 3 4 7 9
0 1 1 0 1 0 0

+/ 4 E. 3 4 4 3 4 7 9
3

so

f =: +/ @: E.

eg

4 f 3 4 4 3 4 7 9 
3
(1 0) f (1 0 3 2 4 1 0 3)
2