Search code examples
arraysrankj

Misunderstanding of J Tally(#)


In J, to find the number of elements you can use # right?

e.g.

# 2 3 4 5 6
5

OK. So what about a multidimensional array

b=: 2 3 4 $ i.2

   b
0 1 0 1
0 1 0 1
0 1 0 1

0 1 0 1
0 1 0 1
0 1 0 1

Here #b is 2. I guess because the first dimension has length 2. i.e. the frame of the array.

So if I change it slightly:

b=:3 2 4 $ i.2
   b
0 1 0 1
0 1 0 1

0 1 0 1
0 1 0 1

0 1 0 1
0 1 0 1

This has tally 3, because the leading dimension has length 3, right?

But I can't explain this:

#\b
1 2 3

I run tally through the elements of b. So I would think each 2x4 sub array would be used and I would expect #\b to give

2 2 2

because:

c=:2 4 $i.2
   c
0 1 0 1
0 1 0 1
   #c
2

So my question is, why is #\b = 1 2 3? I think it has something to do with verb ranks, right? I'm struggling to understand this topic...


Solution

  • The easiest way to see what's going on is to box < your \b:

       <\b
    ┌───────┬───────┬───────┐
    │0 1 0 1│0 1 0 1│0 1 0 1│
    │0 1 0 1│0 1 0 1│0 1 0 1│
    │       │       │       │
    │       │0 1 0 1│0 1 0 1│
    │       │0 1 0 1│0 1 0 1│
    │       │       │       │
    │       │       │0 1 0 1│
    │       │       │0 1 0 1│
    └───────┴───────┴───────┘
    

    u\y applies u to y's prefixes:

    <\1 2 3
    ┌─┬───┬─────┐
    │1│1 2│1 2 3│
    └─┴───┴─────┘
    #\1 2 3
    1 2 3
    */\1 2 3
    1 2 6
    

    So, #\b gives you the number of items of each of b's prefixes.

    What you probably thought you would get, is the 2-rank number of items of b:

    #"2 b
    2 2 2
    <"2 b
    ┌───────┬───────┬───────┐
    │0 1 0 1│0 1 0 1│0 1 0 1│
    │0 1 0 1│0 1 0 1│0 1 0 1│
    └───────┴───────┴───────┘