Take and Drop

𝕩 5↑𝕩 5↓𝕩 's' 't' 'a' 'r' 't' 'e' 'n' 'd'

The basic idea of Take (↑) is to get the first few elements of a list, while Drop (↓) removes those and returns the rest. Then they are extended in like a billion ways.

These extensions can be combined as well, so there are a lot of possibilities. A good picture to have in mind is cutting out a corner of the array 𝕩. This is because the result 𝕨↑𝕩 or 𝕨↓𝕩 always aligns with one side of 𝕩 along each axis, so it aligns with the corner where those sides meet.

The result d↓𝕩 is always the same as t↑𝕩 for some other argument t, but computing t wouldn't be too convenient. The reverse isn't true: only Take can insert fills, so results that include them can't come from Drop.

One axis

Let's start with a natural number 𝕨. Take gives the first 𝕨 major cells of 𝕩 (or elements of a list), while Drop gives all but the first 𝕨.

↗️
    4 ↑ "take and drop"
"take"
    4 ↓ "take and drop"
" and drop"

    1 ↓ >"maj"β€Ώ"orc"β€Ώ"ell"
β”Œβ”€     
β•΅"orc  
  ell" 
      β”˜

If 𝕨 is too large it's usually not a problem. For Take, fill elements are added to the end to bring 𝕩 up to the required lengthβ€”although this will fail if 𝕩 has no fill element. For Drop, the result is an empty array.

↗️
    ↕6
⟨ 0 1 2 3 4 5 ⟩

    10 ↑ ↕6
⟨ 0 1 2 3 4 5 0 0 0 0 ⟩

    10 ↓ ↕6
⟨⟩

    β‰’ 5 ↓ ↕3β€Ώ9β€Ώ2
⟨ 0 9 2 ⟩

If 𝕩 is an atom or unit array, it's converted to a list first. For Take this is useful to make an array of mostly fills; for Drop it's pretty much useless.

↗️
    10 ↑ 9
⟨ 9 0 0 0 0 0 0 0 0 0 ⟩

    3 ↓ <"element"
⟨⟩

Negative argument

If 𝕨 is negative then wraps around the other side to take or drop from the end of 𝕩. It's a lot like negative indices in Select (⊏), but while negative indices are asymmetricβ€”0 is the first entry but Β―1 is the lastβ€”this case is symmetric. It's because the place to cut is always before the index 𝕨, cancelling out the negative index asymmetry.

↗️
    3 ↑ "abcdeEDCBA"
"abc"

    Β―3 ↑ "abcdeEDCBA"  # Last three
"CBA"

    Β―3 ↓ "abcdeEDCBA"  # All but the last three
"abcdeED"

What about 0? It behaves like it's both positive and negative. For Take, the first 0 and last 0 cells are indistinguishable, because they're both empty. For Drop, if you remove 0 cells it doesn't matter whether you start at the front or the back, because you're not going to do anything either way.

↗️
    0 ↑ 4β€Ώ3β€Ώ2  # Nothing
⟨⟩

    0 ↓ 4β€Ώ3β€Ώ2  # Everything
⟨ 4 3 2 ⟩

If |𝕨 is too large, then Take will insert fills at the beginning to keep the result aligned with 𝕩 at the end. Drop returns an empty array as in the positive case. So unlike Rotate (⌽), which is completely cyclical, Take and Drop work cyclically only around 0.

↗️
    Β―6 ↑ "xy"
"    xy"

Multiple axes

In the general case 𝕨 is a list of integers. They're matched with the leading axes of 𝕩, so that each affects one axis independently from the others.

↗️
    ⊒ m ← (10×↕5) +⌜ ↕7
β”Œβ”€                      
β•΅  0  1  2  3  4  5  6  
  10 11 12 13 14 15 16  
  20 21 22 23 24 25 26  
  30 31 32 33 34 35 36  
  40 41 42 43 44 45 46  
                       β”˜

    Β―4β€Ώ2 ↑ m  # Last four rows; first two columns
β”Œβ”€       
β•΅ 10 11  
  20 21  
  30 31  
  40 41  
        β”˜

    Β―4β€Ώ2 ↓ m
β”Œβ”€           
β•΅ 2 3 4 5 6  
            β”˜

Now Take and Drop taken together don't include the whole array. Take includes the elements that are selected on every axis, while Drop excludes the ones selected on any axis. They are opposite corners that meet at some point in the middle of the array (here, at the spot between 2 and 11).

Any integer values at all can be used, in any combination. Here one axis is shortened and the other's padded with fills. The result of Take has shape |𝕨, maybe plus some trailing axes from 𝕩. Of course, if that's too big for your available memory, your BQN implementation probably can't compute it for you!

↗️
    3β€ΏΒ―12 ↑ m
β”Œβ”€                                
β•΅ 0 0 0 0 0  0  1  2  3  4  5  6  
  0 0 0 0 0 10 11 12 13 14 15 16  
  0 0 0 0 0 20 21 22 23 24 25 26  
                                 β”˜

    β‰’ 9β€ΏΒ―4 ↑ ↕7β€Ώ6β€Ώ5  # Trailing shape example
⟨ 9 4 5 ⟩

If the rank of 𝕩 is smaller than the length of 𝕨, then length-1 axes are added to the beginning until it's equal. Mostly this will be used with Take when 𝕩 is a unit, producing an array that contains 𝕩 and a lot of fills.

↗️
    3β€Ώ4 ↑ <1β€Ώ1
β”Œβ”€                                 
β•΅ ⟨ 1 1 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩  
  ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩  
  ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩ ⟨ 0 0 ⟩  
                                  β”˜

This property also enables a nice little trick with Drop. If 𝕨 is a list of zeros, Drop won't do anythingβ€”except extend the rank of 𝕩. So (rβ₯Š0)↓a, or r β₯ŠβŸœ0βŠΈβ†“ a, ensures a is an array with rank at least r but doesn't change any of the elements. As a special case, βŸ¨βŸ©β†“v Encloses an atom argument but otherwise has no effect.

↗️
    β‰’ (3β₯Š0) ↓ 3
⟨ 1 1 1 ⟩

    β‰’ (3β₯Š0) ↓ ↕3
⟨ 1 1 3 ⟩

    β‰’ (3β₯Š0) ↓ ↕5β€Ώ4β€Ώ3β€Ώ2
⟨ 5 4 3 2 ⟩