J: Coordinates with specific value
Asked Answered
C

2

5

Let's say we have array

0 1 2 3 4 5 8 7 8 9

There are two indexes that have value 8:

(i.10) ([#~8={) 0 1 2 3 4 5 8 7 8 9
6 8

Is there any shorter way to get this result? May be some built-in verb.

But more important. What about higher dimensions? Let's say we have matrix 5x4

1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8

I want to find out what are coordinates with value 6.
I want to get result such (there are three coordinates):

4 1
3 2
2 3

It's pretty basic task and I think it should exist some simple solution.

The same in three dimensions?

Thank you

Capitulation answered 25/9, 2016 at 12:45 Comment(0)
U
3

Verb indices I. almost does the job.

When you have a simple list, I.'s use is straightforward:

I. 8 = 0 1 2 3 4 5 8 7 8 9
6 8 

For higher order matrices you can pair it with antibase #: to get the coordinates in base $ matrix. Eg:

]a =: 4 5 $ 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8

I. 6 = ,a
9 13 17

($a) #: 9 13 17
1 4
2 3
3 2

Similarly, for any number of dimensions: flatten (,), compare (=), get indices (I.) and convert coordinates (($a)&#:):

]coords =: ($a) #: I. 5 = , a =: ? 5 6 7 $ 10
0 0 2
0 2 1
0 2 3
...
(<"1 coords) { a
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5

By the way, you can write I. x = y as x (I.@:=) y for extra performance. It is special code for

indices where x f y

Ulane answered 25/9, 2016 at 15:54 Comment(0)
B
5

Using Sparse array functionality ($.) provides a very fast and lean solution that also works for multiple dimensions.

   ]a=: 5 ]\ 1 + i. 8
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
   6 = a
0 0 0 0 0
0 0 0 0 1
0 0 0 1 0
0 0 1 0 0
   4 $. $. 6 = a
1 4
2 3
3 2

Tacitly:

   getCoords=: 4 $. $.
   getCoords 6 = a ,: a
0 1 4
0 2 3
0 3 2
1 1 4
1 2 3
1 3 2
Blumenthal answered 25/9, 2016 at 20:3 Comment(1)
Never noticed that before. Very interesting. On a 1e5 x 1e5 integer matrix, $. is about 3 times faster and uses 1/10 space.Ulane
U
3

Verb indices I. almost does the job.

When you have a simple list, I.'s use is straightforward:

I. 8 = 0 1 2 3 4 5 8 7 8 9
6 8 

For higher order matrices you can pair it with antibase #: to get the coordinates in base $ matrix. Eg:

]a =: 4 5 $ 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8

I. 6 = ,a
9 13 17

($a) #: 9 13 17
1 4
2 3
3 2

Similarly, for any number of dimensions: flatten (,), compare (=), get indices (I.) and convert coordinates (($a)&#:):

]coords =: ($a) #: I. 5 = , a =: ? 5 6 7 $ 10
0 0 2
0 2 1
0 2 3
...
(<"1 coords) { a
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5

By the way, you can write I. x = y as x (I.@:=) y for extra performance. It is special code for

indices where x f y

Ulane answered 25/9, 2016 at 15:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.