aboutsummaryrefslogtreecommitdiff
path: root/doc/pick.md
blob: 254c64ec8599bb254d3abf1380945a444994d1c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
*View this file with results and syntax highlighting [here](https://mlochbaum.github.io/BQN/doc/pick.html).*

# Pick

Pick (`⊑`) chooses elements from `𝕩` based on [index](indices.md) lists from `𝕨`. `𝕨` can be a plain list, or even one number if `𝕩` is a list, in order to get one element from `𝕩`. It can also be an array of index lists, or have deeper array structure: each index list will be replaced with the element of `𝕩` at that index, effectively applying to `𝕨` at [depth](depth.md#the-depth-modifier) 1.

With no `𝕨`, monadic `⊑𝕩` takes the first element of `𝕩` in index order, with an error if `𝕩` is empty.

While sometimes "scatter-point" indexing is necessary, using Pick to select multiple elements from `𝕩` is less array-oriented than [Select](select.md) (`⊏`), and probably slower. Consider rearranging your data so that you can select along axes instead of picking out elements.

## One element

When the left argument is a number, Pick gets an element from a list:

        2 ⊑ 0‿1‿2‿3‿4
        2 ⊑ "abc"
        2 ⊑ ⟨@, 0‿1‿2‿3, "abc"⟩

A negative number `𝕨` behaves like `𝕨+≠𝕩`, so that `¯1` will select the last element, and `-≠𝕩` the first. A number in `𝕨` must be an integer less than `≠𝕩` but not less than `-≠𝕩`.

        ¯2 ⊑ 0‿1‿2‿3‿4
        ¯2 ⊑ "abc"

Making `𝕩` a list is only a special case. In general `𝕨` can be a list of numbers whose length is `𝕩`'s rank. So when `=𝕩` is 1, `𝕨` can be length-1 list. For convenience, a number is also allowed, but not an enclosed number (which could be confused with the nested case).

        ⟨2,0⟩ ⊑ ↕4‿5

Above we see that picking from the result of [Range](range.md) gives the index. For something slightly more interesting, here's a character array:

        ⊢ a ← 'a' + ⥊⟜(↕×´) 4‿5
        2‿0 ⊑ a
        1‿¯1 ⊑ a

This applies even if `𝕩` is a unit. By definition it has rank 0, so the only possible value for `𝕨` is the empty list. This extracts an [enclosed](enclose.md) element, and returns an atom unchanged—the atom is promoted to an array by enclosing it, then the action of Pick undoes this. But there's rarely a reason to use this case, because the monadic form First accomplishes the same thing.

        ⟨⟩ ⊑ <'a'
        ⟨⟩ ⊑ 'a'

### First

With no left argument, `⊑` is called First, and performs a slight generalization of Pick with a default left argument `0¨≢𝕩`. For a non-empty array it returns the first element in index order.

        ⊑ <'a'
        ⊑ "First"
        ⊑ ↕4‿2‿5‿1

If `𝕩` is empty then First results in an error, like Pick.

        ⊑ ""
        ⊑ ≢π

In APL it's common to get the last element of a list with an idiom that translates to `⊑⌽`, or First-[Reverse](reverse.md). In BQN the most straightforward way is to select with index `¯1` instead. I also sometimes use [Fold](fold.md) with the Right [identity function](identity.md).

        ⊑⌽ "last"
        ¯1⊑ "last"
        ⊢´ "last"

## Many elements

Pick also accepts a list of indices:

        a  # Defined above

        ⟨2‿0, 1‿¯1, 3‿1, ¯1‿¯1⟩ ⊑ a

These indices have to be lists, since if they're numbers it just looks like `𝕨` is an index list for one element.

        ⟨2,1,0,¯1⟩ ⊑ "abc"  # 𝕩 doesn't have rank 4!

        ⟨2,1,0,¯1⟩ ⥊¨⊸⊑ "abc"

        ⟨2,1,0,¯1⟩ ⊏ "abc"  # Better way

It's much more general than just a list of indices though. As long as your indices are lists, you can arrange them in any array structure with arbitrary nesting.

        ⟨2‿0, ⟨⟨1‿¯1, 3‿1⟩, ¯1‿¯1⟩⟩ ⊑ a

        (⟨2‿0, 1‿¯1⟩≍⟨3‿1, ¯1‿¯1⟩) ⊑ a

        (⟨2‿0, <1‿¯1⟩≍⟨<3‿1, ¯1‿¯1⟩) ⊑ a

This option is easily described using the [Depth modifier](depth.md#the-depth-modifier). Pick applies to depth-1 components of the left argument and the entire right argument, which corresponds to a depth operand of `1‿∞`. The left argument components have to be lists of numbers, or Pick gives an error.

        (⟨2‿0, <1‿¯1⟩≍⟨<3‿1, ¯1‿¯1⟩) ⊑⚇1‿∞ a

        ⟨⟨2,3⟩,1⟩ ⊑ a  # 1 isn't a valid index