1

Given two matrices A and B with the same number of columns I would like to know if there are any rows which are the same in A and B. In Dyalog APL I can use the function split like this:

(↓A) ∊ ↓B

Is there a way to calculate the same result without the split function?

Adám
  • 6,573
  • 20
  • 37
August Karlstrom
  • 10,773
  • 7
  • 38
  • 60

2 Answers2

2

What you've found is a design flaw in Membership in that it implies that the right argument is a set of scalars rather than looking at it as a collection of major cells. This precluded extension according to Leading axis theory. However, Index of was extended thus, and so we can use the fact that it returns the index beyond the end of of the lookup array when a major cell isn't found:

      ⎕← A ← 4 2⍴2 7 1 8 2 8 1 8
2 7
1 8
2 8
1 8
      ⎕← B ← 5 2⍴1 6 1 8 0 3 3 9 8 9
1 6
1 8
0 3
3 9
8 9
      (↓A) ∊ ↓B
0 1 0 1
      Membership ← {(≢⍵) ≥ ⍵⍳⍺}
      A Membership B
0 1 0 1

Try it online!

This can also be written tacitly as Membership ← ⊢∘≢ ≥ ⍳⍨.

Either way, note that avoiding the detour of nested arrays leads to significant speed gains:

      A←?1000 4⍴10
      B←?1000 4⍴10
      ]runtime -compare "(↓A) ∊ ↓B" "A Membership B"
                                                                          
  (↓A) ∊ ↓B      → 1.6E¯4 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕ 
  A Membership B → 8.9E¯6 | -95% ⎕⎕                                       
Adám
  • 6,573
  • 20
  • 37
  • Thanks for the detailed answer. I tried to define your membership function in GNU APL but I got a range error in ⍵ ⍳ ⍺. My conclusion is that in GNU APL the left argument of iota must be a vector. – August Karlstrom Oct 30 '20 at 09:22
  • Right, GNU APL uses [a different extension to dyadic `⍳`](https://www.gnu.org/software/apl/apl.html#Generalized-dyadic-_005b_003f_005d). I used a Dyalog specific feature since you tagged your question [tag:dyalog]. In GNU APL, you can use `Membership←{∨/⍺≡⍤(¯1+≢⍴⍵)⍤(¯1 0+≢⍴⍵)⊢⍵}` in general, or `Membership←{∨/⍺≡⍤1⍤1 2⊢⍵}` in this specific case. – Adám Oct 30 '20 at 10:09
  • Thanks! I added the Dyalog tag since the question mentions Dyalog APL. – August Karlstrom Oct 30 '20 at 13:41
  • 1
    @AugustKarlstrom Oh wow, I completely misunderstood your question. You mean to ask how to write Dyalog's monadic `↓` in GNU APL. Well, that's `⊂⍤1` although what you often need is to split into major cells, i.e. `⊂⍤¯1`. – Adám Oct 30 '20 at 14:28
  • No, your interpretation of the question was mostly correct; what I'm looking for is a portable way to implement *RowMemberOf* so to speak. Now I also know how to implement the function *split*. – August Karlstrom Oct 31 '20 at 08:57
0

Something like A⍳B would show not only membership but location of equal rows.

DevonMcC
  • 435
  • 4
  • 4