3

I'm new to APL and I would like to find the position of an element(s) within a vector. For example, if I create a vector of 50 random numbers:

lst ←  50 ? 100

How can I find the positions of 91 assuming it occurs 3 times in the vector?

Thanks.

awyr_agored
  • 613
  • 3
  • 19
  • 2
    `50?100` chooses randomly 50 _distinct_ ints from `⍳100` (that is 0...99 or 1...100 depending on `⎕IO`). 91 will never occur more than once. You probably want `?50⍴100`. – ngn Jun 16 '18 at 12:22
  • Thanks ngn, I should have realised that ? generates unique values only – awyr_agored Jun 16 '18 at 13:10

4 Answers4

4

I'm not an expert, but a simple way is to just select the elements from ⍳ 100 where the corresponding element in lst is 91

(lst=91)/⍳100
Probie
  • 1,371
  • 7
  • 15
  • 1
    Wouldn't it be better to write `≢lst` rather than `⍳100` just in case `lst` length changes? – Adám Jun 18 '18 at 08:18
4

With Dyalog 16.0, you can use the new monadic function "Where".

⍸lst=91

lst=91 gives a vector of 0s and 1s. Applying on this gives the locations of all the 1s. This also works if lst is a matrix.

user41805
  • 523
  • 1
  • 9
  • 21
1

Thanks to ngn, Cows_quack and Probie. I should have read Mastering Dyalog APL more carefully as it also mentions this on page 126. So taking all the answers together:

⍝ Generate a list of 100 non-unique random numbers
lst ← ?100⍴100

⍝ How many times does 1, for example, appear in the vector Using the compress function?
+/ (lst = 1)  ⍝ Appears twice
2

⍝ Find the locations of 1 in the vector
(lst = 1) / ⍳ ⍴ lst
2 37          ⍝ Positions 2 and 37

So to break down the solution; (i) (lst = 1) generates a boolean vector where true occurs where the int value of 1 exists; (ii) compress the lst vector by the boolean vector creates a new vector with the positions of 'true' in lst.

Correct me if my description is off?

SIMPLIFICATION:

Using the 'Where' function makes it more readable (though the previous method shows how the APL mindset of array programming is used to solve it):

⍸lst=1
2 37          ⍝ Positions 2 and 37

Thanks for your time on this!

Regards

awyr_agored
  • 613
  • 3
  • 19
1

While your question has already been amply answered, you may be interested in the Key operator, . When its derived function is applied monadically, it takes a single operand and applies it once for each element in the argument. The function is called with the unique element as left argument and the list of its indices as right argument:

      lst ← ?100⍴10
      {⍺ ⍵}⌸lst
┌──┬──────────────────────────────────────────┐
│3 │1 3 9 28 37 38 55 70 88                   │
├──┼──────────────────────────────────────────┤
│10│2 6 13 17 30 59 64 66 71 82 83 96         │
├──┼──────────────────────────────────────────┤
│7 │4 5 12 15 20 52 54 68 74 85 89 91 92      │
├──┼──────────────────────────────────────────┤
│9 │7 11 24 47 53 58 69 86 90                 │
├──┼──────────────────────────────────────────┤
│8 │8 14 16 21 43 51 63 67 73 80              │
├──┼──────────────────────────────────────────┤
│2 │10 18 26 27 34 36 48 78 79 87             │
├──┼──────────────────────────────────────────┤
│1 │19 25 31 32 33 42 57 65 75 84 97 98 99 100│
├──┼──────────────────────────────────────────┤
│6 │22 23 45 46 50 60 76 94                   │
├──┼──────────────────────────────────────────┤
│5 │29 49 56 61 72 77 93 95                   │
├──┼──────────────────────────────────────────┤
│4 │35 39 40 41 44 62 81                      │
└──┴──────────────────────────────────────────┘

Try it online!

Adám
  • 6,573
  • 20
  • 37