aboutsummaryrefslogtreecommitdiff
path: root/docs/doc/group.html
blob: a79305ccecbbaafe68b52219df8a12225cd2e405 (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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<head>
  <link href="../favicon.ico" rel="shortcut icon" type="image/x-icon"/>
  <link href="../style.css" rel="stylesheet"/>
  <title>BQN: Group</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">doc</a></div>
<h1 id="group"><a class="header" href="#group">Group</a></h1>
<p>BQN replaces the Key operator from J or Dyalog APL, and <a href="https://aplwiki.com/wiki/Partition_representations">many forms of partitioning</a>, with a single (ambivalent) Group function <code><span class='Function'></span></code>. This function is somewhat related to the K function <code><span class='Function'>=</span></code> of the same name, but results in an array rather than a dictionary.</p>
<svg viewBox='-344 -121.8 640 226.8'>
  <g text-anchor='middle' font-family='BQN,monospace'>
    <rect class='code' stroke-width='1' rx='12' x='-280' y='-102.2' width='512' height='204.4'/>
    <g font-size='24px' text-anchor='start' fill='currentColor' opacity='0.9'><text x='-256' y='-98'>Group</text></g>
    <g font-size='18px'><text x='-160' y='-64.4'><tspan class='Number'>0</tspan></text><text x='-80' y='-64.4'><tspan class='Number'>¯1</tspan></text><text x='0' y='-64.4'><tspan class='Number'>¯1</tspan></text><text x='80' y='-64.4'><tspan class='Number'>2</tspan></text><text x='160' y='-64.4'><tspan class='Number'>0</tspan></text><text x='-160' y='-36.4'><tspan class='String'>"zero"</tspan></text><text x='-80' y='-36.4'><tspan class='String'>"one"</tspan></text><text x='0' y='-36.4'><tspan class='String'>"two"</tspan></text><text x='80' y='-36.4'><tspan class='String'>"three"</tspan></text><text x='160' y='-36.4'><tspan class='String'>"four"</tspan></text><text x='-128' y='47.6'><tspan class='String'>"zero"</tspan></text><text x='-48' y='47.6'><tspan class='String'>"four"</tspan></text><text x='128' y='47.6'><tspan class='String'>"three"</tspan></text><text x='-88' y='84'><tspan class='Number'>0</tspan></text><text x='40' y='84'><tspan class='Number'>1</tspan></text><text x='128' y='84'><tspan class='Number'>2</tspan></text></g>
    <g font-size='16px' text-anchor='end'>
      <text x='-224' y='-64.4'><tspan class='Value'>𝕨</tspan></text>
      <text x='-224' y='-36.4'><tspan class='Value'>𝕩</tspan></text>
      <text x='-224' y='47.6'><tspan class='Value'>𝕨</tspan><tspan class='Function'></tspan><tspan class='Value'>𝕩</tspan></text>
    </g>
    <g class='yellow' stroke-width='2'>
      <line x1='-160' x2='-128' y1='-30.8' y2='33.6'/>
      <line x1='160' x2='-48' y1='-30.8' y2='33.6'/>
      <line x1='80' x2='128' y1='-30.8' y2='33.6'/>
    </g>
    <g class='green' stroke-width='1.5' style='fill:none'>
      <path d='M-176 33.6v28h176v-28'/>
      <path d='M24 33.6v28h32v-28'/>
      <path d='M80 33.6v28h96v-28'/>
    </g>
  </g>
</svg>

<h2 id="definition"><a class="header" href="#definition">Definition</a></h2>
<p>Group operates on a list of atomic-number <a href="indices.html">indices</a> <code><span class='Value'>𝕨</span></code> and an array <code><span class='Value'>𝕩</span></code>, treated as a list of its major cells, to produce a list of groups, each containing some of the cells from <code><span class='Value'>𝕩</span></code>. The two arguments have the same length, and each cell in <code><span class='Value'>𝕩</span></code> is paired with the index in <code><span class='Value'>𝕨</span></code> at the same position, which indicates which result group should include that cell.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MOKAvzHigL8y4oC/MOKAvzEg4omNICJhYmNkZSIgICMgQ29ycmVzcG9uZGluZyBpbmRpY2VzIGFuZCB2YWx1ZXMKCjDigL8x4oC/MuKAvzDigL8xIOKKlCAiYWJjZGUiICAjIFZhbHVlcyBncm91cGVkIGJ5IGluZGV4">↗️</a><pre>    <span class='Number'>0</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>2</span><span class='Ligature'></span><span class='Number'>0</span><span class='Ligature'></span><span class='Number'>1</span> <span class='Function'></span> <span class='String'>&quot;abcde&quot;</span>  <span class='Comment'># Corresponding indices and values
</span>┌─                     
╵ 0   1   2   0   1    
  'a' 'b' 'c' 'd' 'e'  
                      ┘

    <span class='Number'>0</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>2</span><span class='Ligature'></span><span class='Number'>0</span><span class='Ligature'></span><span class='Number'>1</span> <span class='Function'></span> <span class='String'>&quot;abcde&quot;</span>  <span class='Comment'># Values grouped by index
</span>⟨ "ad" "be" "c" ⟩
</pre>
<p>A few extra options can be useful in some circumstances. First, an &quot;index&quot; of <code><span class='Number'>¯1</span></code> in <code><span class='Value'>𝕨</span></code> indicates that the corresponding cell should be dropped and not appear in the result. Second, <code><span class='Value'>𝕨</span></code> is allowed to have an extra element after the end, which gives a minimum length for the result: otherwise, the result will be just long enough to accomodate the highest index in <code><span class='Value'>𝕨</span></code> (it might seem like the last element should be treated like an index, making the minimum length one higher, but the length version usually leads to simpler arithmetic).</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MOKAv8KvMeKAvzLigL8y4oC/wq8xIOKKlCAiYWJjZGUiICAjIERyb3AgYyBhbmQgZQoKMOKAvzHigL8y4oC/MuKAvzHigL82IOKKlCAiYWJjZGUiICAjIExlbmd0aC02IHJlc3VsdA==">↗️</a><pre>    <span class='Number'>0</span><span class='Ligature'></span><span class='Number'>¯1</span><span class='Ligature'></span><span class='Number'>2</span><span class='Ligature'></span><span class='Number'>2</span><span class='Ligature'></span><span class='Number'>¯1</span> <span class='Function'></span> <span class='String'>&quot;abcde&quot;</span>  <span class='Comment'># Drop c and e
</span>⟨ "a" ⟨⟩ "cd" ⟩

    <span class='Number'>0</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>2</span><span class='Ligature'></span><span class='Number'>2</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>6</span> <span class='Function'></span> <span class='String'>&quot;abcde&quot;</span>  <span class='Comment'># Length-6 result
</span>⟨ "a" "be" "cd" ⟨⟩ ⟨⟩ ⟨⟩ ⟩
</pre>
<p>A third extension is that <code><span class='Value'>𝕨</span></code> doesn't really have to be a list: if not, then it groups <code><span class='Function'>-=</span><span class='Value'>𝕨</span></code>-cells of <code><span class='Value'>𝕩</span></code> instead of just <code><span class='Number'>¯1</span></code>-cells. These cells are placed in index order. This extension isn't compatible with the second option from above, because it's usually not possible to add just one extra element to a non-list array. One usage is to group the diagonals of a table. See if you can figure out how the code below does this.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oqiIGEg4oaQICdhJyvipYrin5wo4oaVw5fCtCkz4oC/NQoKKCvijJzCtMK34oaVwqjiiaIp4oq44oqUIGE=">↗️</a><pre>    <span class='Function'></span> <span class='Value'>a</span> <span class='Gets'></span> <span class='String'>'a'</span><span class='Function'>+⥊</span><span class='Modifier2'></span><span class='Paren'>(</span><span class='Function'>↕×</span><span class='Modifier'>´</span><span class='Paren'>)</span><span class='Number'>3</span><span class='Ligature'></span><span class='Number'>5</span>
┌─       
╵"abcde  
  fghij  
  klmno" 
        ┘

    <span class='Paren'>(</span><span class='Function'>+</span><span class='Modifier'>⌜´</span><span class='Nothing'>·</span><span class='Function'></span><span class='Modifier'>¨</span><span class='Function'></span><span class='Paren'>)</span><span class='Modifier2'></span><span class='Function'></span> <span class='Value'>a</span>
⟨ "a" "bf" "cgk" "dhl" "eim" "jn" "o" ⟩
</pre>
<p>For a concrete example, we might choose to group a list of words by length. Within each group, cells maintain the ordering they had in the list originally.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=cGhyYXNlIOKGkCAiQlFOIuKAvyJ1c2VzIuKAvyJub3RhdGlvbiLigL8iYXMi4oC/ImEi4oC/InRvb2wi4oC/Im9mIuKAvyJ0aG91Z2h0IgriiY3LmCDiiaDCqOKKuOKKlCBwaHJhc2U=">↗️</a><pre>    <span class='Value'>phrase</span> <span class='Gets'></span> <span class='String'>&quot;BQN&quot;</span><span class='Ligature'></span><span class='String'>&quot;uses&quot;</span><span class='Ligature'></span><span class='String'>&quot;notation&quot;</span><span class='Ligature'></span><span class='String'>&quot;as&quot;</span><span class='Ligature'></span><span class='String'>&quot;a&quot;</span><span class='Ligature'></span><span class='String'>&quot;tool&quot;</span><span class='Ligature'></span><span class='String'>&quot;of&quot;</span><span class='Ligature'></span><span class='String'>&quot;thought&quot;</span>
    <span class='Function'></span><span class='Modifier'>˘</span> <span class='Function'></span><span class='Modifier'>¨</span><span class='Modifier2'></span><span class='Function'></span> <span class='Value'>phrase</span>
┌─                   
╵ ⟨⟩                 
  ⟨ "a" ⟩            
  ⟨ "as" "of" ⟩      
  ⟨ "BQN" ⟩          
  ⟨ "uses" "tool" ⟩  
  ⟨⟩                 
  ⟨⟩                 
  ⟨ "thought" ⟩      
  ⟨ "notation" ⟩     
                    ┘
</pre>
<p>(Could we define <code><span class='Value'>phrase</span></code> more easily? See <a href="#partitioning">below</a>.)</p>
<p>If we'd like to ignore words of 0 letters, or more than 5, we can set all word lengths greater than 5 to 0, then reduce the lengths by 1. Two words end up with left argument values of ¯1 and are omitted from the result.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MSAty5wg4omk4p+cNeKKuMOXIOKJoMKoIHBocmFzZQoK4omNy5ggezEty5ziiaTin5w14oq4w5fiiaDCqPCdlal94oq44oqUIHBocmFzZQ==">↗️</a><pre>    <span class='Number'>1</span> <span class='Function'>-</span><span class='Modifier'>˜</span> <span class='Function'></span><span class='Modifier2'></span><span class='Number'>5</span><span class='Modifier2'></span><span class='Function'>×</span> <span class='Function'></span><span class='Modifier'>¨</span> <span class='Value'>phrase</span>
⟨ 2 3 ¯1 1 0 3 1 ¯1 ⟩

    <span class='Function'></span><span class='Modifier'>˘</span> <span class='Brace'>{</span><span class='Number'>1</span><span class='Function'>-</span><span class='Modifier'>˜</span><span class='Function'></span><span class='Modifier2'></span><span class='Number'>5</span><span class='Modifier2'></span><span class='Function'>×≠</span><span class='Modifier'>¨</span><span class='Value'>𝕩</span><span class='Brace'>}</span><span class='Modifier2'></span><span class='Function'></span> <span class='Value'>phrase</span>
┌─                   
╵ ⟨ "a" ⟩            
  ⟨ "as" "of" ⟩      
  ⟨ "BQN" ⟩          
  ⟨ "uses" "tool" ⟩  
                    ┘
</pre>
<p>Note that the length of the result is determined by the largest index. So the result never includes trailing empty groups. A reader of the above code might expect 5 groups (lengths 1 through 5), but there are no words of length 5, so the last group isn't there. To ensure the result always has 5 groups, we can add a <code><span class='Number'>5</span></code> at the end of the left argument.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4omNy5ggezXiiL7LnDEty5ziiaTin5w14oq4w5fiiaDCqPCdlal94oq44oqUIHBocmFzZQ==">↗️</a><pre>    <span class='Function'></span><span class='Modifier'>˘</span> <span class='Brace'>{</span><span class='Number'>5</span><span class='Function'></span><span class='Modifier'>˜</span><span class='Number'>1</span><span class='Function'>-</span><span class='Modifier'>˜</span><span class='Function'></span><span class='Modifier2'></span><span class='Number'>5</span><span class='Modifier2'></span><span class='Function'>×≠</span><span class='Modifier'>¨</span><span class='Value'>𝕩</span><span class='Brace'>}</span><span class='Modifier2'></span><span class='Function'></span> <span class='Value'>phrase</span>
┌─                   
╵ ⟨ "a" ⟩            
  ⟨ "as" "of" ⟩      
  ⟨ "BQN" ⟩          
  ⟨ "uses" "tool" ⟩  
  ⟨⟩                 
                    ┘
</pre>
<h3 id="group-indices"><a class="header" href="#group-indices">Group Indices</a></h3>
<p>Above, Group has two arguments, and <code><span class='Value'>𝕨</span></code> gives the indices and <code><span class='Value'>𝕩</span></code> is the values to be grouped. In the one-argument case, <code><span class='Value'>𝕩</span></code> now gives the result indices, and the values grouped are indices related to <code><span class='Value'>𝕩</span></code>. For a numeric list, <code><span class='Function'></span><span class='Value'>𝕩</span></code> is <code><span class='Value'>𝕩</span><span class='Function'>⊔↕≠</span><span class='Value'>𝕩</span></code>.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4omNy5gg4oqUIDLigL8z4oC/wq8x4oC/Mg==">↗️</a><pre>    <span class='Function'></span><span class='Modifier'>˘</span> <span class='Function'></span> <span class='Number'>2</span><span class='Ligature'></span><span class='Number'>3</span><span class='Ligature'></span><span class='Number'>¯1</span><span class='Ligature'></span><span class='Number'>2</span>
┌─         
╵ ⟨⟩       
  ⟨⟩       
  ⟨ 0 3 ⟩  
  ⟨ 1 ⟩    
          ┘
</pre>
<p>Here, the index 2 appears at indices 0 and 3 while the index 3 appears at index 1.</p>
<p>But <code><span class='Value'>𝕩</span></code> can also be a list of numeric arrays. In this case the indices <code><span class='Function'>↕∾≢</span><span class='Modifier'>¨</span><span class='Value'>𝕩</span></code> will be grouped by <code><span class='Value'>𝕩</span></code> according to the multidimensional grouping documented in the next section. Since the argument to <a href="range.html">Range</a> (<code><span class='Function'></span></code>) is now a list, each index to be grouped is a list instead of a number. As with <code><span class='Function'></span></code>, the depth of the result of Group Indices is always one greater than that of its argument. One consequence is that for an array <code><span class='Value'>a</span></code> of any rank, <code><span class='Function'>⊔⋈</span><span class='Value'>a</span></code> groups the indices <code><span class='Function'>↕≢</span><span class='Value'>a</span></code>.</p>
<h3 id="multidimensional-grouping"><a class="header" href="#multidimensional-grouping">Multidimensional grouping</a></h3>
<p>Dyadic Group allows the right argument to be grouped along multiple axes by using a nested left argument. In this case, the left argument must be a list of numeric lists, and the result has rank <code><span class='Function'></span><span class='Value'>𝕨</span></code> while its elements—as always—have the same rank as <code><span class='Value'>𝕩</span></code>. The result shape is <code><span class='Number'>1</span><span class='Function'>+⌈</span><span class='Modifier'>´¨</span><span class='Value'>𝕨</span></code>, while the shape of element <code><span class='Value'>i</span><span class='Function'></span><span class='Value'>𝕨</span><span class='Function'></span><span class='Value'>𝕩</span></code> is <code><span class='Value'>i</span><span class='Function'>+</span><span class='Modifier'>´</span><span class='Modifier2'></span><span class='Function'>=</span><span class='Modifier'>¨</span><span class='Value'>𝕨</span></code>. If every element of <code><span class='Value'>𝕨</span></code> is sorted ascending and contains only non-negative numbers, we have <code><span class='Value'>𝕩</span><span class='Function'>≡∾</span><span class='Value'>𝕨</span><span class='Function'></span><span class='Value'>𝕩</span></code>, that is, <a href="join.html#join">Join</a> is the inverse of Partition.</p>
<p>Here we split up a rank-2 array into a rank-2 array of rank-2 arrays. Along the first axis we simply separate the first pair and second pair of rows—a partition. Along the second axis we separate odd from even indices.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4p+oMOKAvzDigL8x4oC/MSww4oC/MeKAvzDigL8x4oC/MOKAvzHigL8w4p+pIOKKlCAoMTDDl+KGlTQpK+KMnOKGlTc=">↗️</a><pre>    <span class='Bracket'></span><span class='Number'>0</span><span class='Ligature'></span><span class='Number'>0</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>1</span><span class='Separator'>,</span><span class='Number'>0</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>0</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>0</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>0</span><span class='Bracket'></span> <span class='Function'></span> <span class='Paren'>(</span><span class='Number'>10</span><span class='Function'>×↕</span><span class='Number'>4</span><span class='Paren'>)</span><span class='Function'>+</span><span class='Modifier'></span><span class='Function'></span><span class='Number'>7</span>
┌─                              
╵ ┌─              ┌─            
  ╵  0  2  4  6   ╵  1  3  5    
    10 12 14 16     11 13 15    
                ┘            ┘  
  ┌─              ┌─            
  ╵ 20 22 24 26   ╵ 21 23 25    
    30 32 34 36     31 33 35    
                ┘            ┘  
                               ┘
</pre>
<p>Each group <code><span class='Value'>i</span><span class='Function'></span><span class='Value'>𝕨</span><span class='Function'></span><span class='Value'>𝕩</span></code> is composed of the cells <code><span class='Value'>j</span><span class='Function'>&lt;</span><span class='Modifier'>¨</span><span class='Modifier2'></span><span class='Function'></span><span class='Value'>𝕩</span></code> such that <code><span class='Value'>i</span><span class='Function'></span><span class='Value'>j</span><span class='Function'></span><span class='Modifier'>¨</span><span class='Value'>𝕨</span></code>. The groups retain their array structure and ordering along each argument axis. Using multidimensional Replicate we can say that <code><span class='Value'>i</span><span class='Function'></span><span class='Value'>𝕨</span><span class='Function'></span><span class='Value'>𝕩</span></code> is <code><span class='Paren'>(</span><span class='Value'>i</span><span class='Function'>=</span><span class='Value'>𝕨</span><span class='Paren'>)</span><span class='Function'>/</span><span class='Value'>𝕩</span></code>.</p>
<h2 id="properties"><a class="header" href="#properties">Properties</a></h2>
<p>Group is closely related to the <a href="replicate.html#inverse">inverse of Indices</a>, <code><span class='Function'>/</span><span class='Modifier'></span></code>. In fact, inverse Indices called on the index argument gives the length of each group:</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4omgwqjiipQgMuKAvzPigL8x4oC/Mgov4oG84oinIDLigL8z4oC/MeKAvzI=">↗️</a><pre>    <span class='Function'></span><span class='Modifier'>¨</span><span class='Function'></span> <span class='Number'>2</span><span class='Ligature'></span><span class='Number'>3</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>2</span>
⟨ 0 1 2 1 ⟩
    <span class='Function'>/</span><span class='Modifier'></span><span class='Function'></span> <span class='Number'>2</span><span class='Ligature'></span><span class='Number'>3</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>2</span>
⟨ 0 1 2 1 ⟩
</pre>
<p>A related fact is that calling Indices on the result lengths of Group sorts all the indices passed to Group (removing any ¯1s). This is a kind of counting sort.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=L+KJoMKo4oqUIDLigL8z4oC/MeKAv8KvMeKAvzI=">↗️</a><pre>    <span class='Function'>/≠</span><span class='Modifier'>¨</span><span class='Function'></span> <span class='Number'>2</span><span class='Ligature'></span><span class='Number'>3</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>¯1</span><span class='Ligature'></span><span class='Number'>2</span>
⟨ 1 2 2 3 ⟩
</pre>
<p>Called dyadically, Group sorts the right argument according to the left and adds some extra structure. If this structure is removed with <a href="join.html#join">Join</a>, Group can be thought of as a kind of sorting.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oi+IDLigL8z4oC/MeKAv8KvMeKAvzIg4oqUICJhYmNkZSIKMuKAvzPigL8x4oC/wq8x4oC/MiB7RuKGkCgw4omk8J2VqCniirgvIOKLhCDwnZWo4o2L4oq44oqP4peLRvCdlal9ICJhYmNkZSI=">↗️</a><pre>    <span class='Function'></span> <span class='Number'>2</span><span class='Ligature'></span><span class='Number'>3</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>¯1</span><span class='Ligature'></span><span class='Number'>2</span> <span class='Function'></span> <span class='String'>&quot;abcde&quot;</span>
"caeb"
    <span class='Number'>2</span><span class='Ligature'></span><span class='Number'>3</span><span class='Ligature'></span><span class='Number'>1</span><span class='Ligature'></span><span class='Number'>¯1</span><span class='Ligature'></span><span class='Number'>2</span> <span class='Brace'>{</span><span class='Function'>F</span><span class='Gets'></span><span class='Paren'>(</span><span class='Number'>0</span><span class='Function'></span><span class='Value'>𝕨</span><span class='Paren'>)</span><span class='Modifier2'></span><span class='Function'>/</span> <span class='Separator'></span> <span class='Value'>𝕨</span><span class='Function'></span><span class='Modifier2'></span><span class='Function'></span><span class='Modifier2'></span><span class='Function'>F</span><span class='Value'>𝕩</span><span class='Brace'>}</span> <span class='String'>&quot;abcde&quot;</span>
"caeb"
</pre>
<p>Group can even be implemented with the same <a href="../implementation/primitive/sort.html#counting-and-bucket-sort">techniques</a> as a bucket sort, making it branchless and fast.</p>
<h2 id="applications"><a class="header" href="#applications">Applications</a></h2>
<p>The obvious application of Group is to group some values according to a known or computed property. If this property isn't a natural number, it can be turned into one using <a href="selfcmp.html#classify">Classify</a> (<code><span class='Function'></span></code>), which numbers the unique values in its argument by first occurrence.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=bG4g4oaQICJQaGVscHMi4oC/IkxhdHluaW5hIuKAvyJCasO4cmdlbiLigL8iQW5kcmlhbm92IuKAvyJCasO4cm5kYWxlbiIKY28g4oaQICJVUyIgICAg4oC/IlNVIiAgICAgIOKAvyJOTyIgICAgIOKAvyJTVSIgICAgICAg4oC/Ik5PIgriiY3LmCBjbyDiipDiirjiipQgbG4=">↗️</a><pre>    <span class='Value'>ln</span> <span class='Gets'></span> <span class='String'>&quot;Phelps&quot;</span><span class='Ligature'></span><span class='String'>&quot;Latynina&quot;</span><span class='Ligature'></span><span class='String'>&quot;Bjørgen&quot;</span><span class='Ligature'></span><span class='String'>&quot;Andrianov&quot;</span><span class='Ligature'></span><span class='String'>&quot;Bjørndalen&quot;</span>
    <span class='Value'>co</span> <span class='Gets'></span> <span class='String'>&quot;US&quot;</span>    <span class='Ligature'></span><span class='String'>&quot;SU&quot;</span>      <span class='Ligature'></span><span class='String'>&quot;NO&quot;</span>     <span class='Ligature'></span><span class='String'>&quot;SU&quot;</span>       <span class='Ligature'></span><span class='String'>&quot;NO&quot;</span>
    <span class='Function'></span><span class='Modifier'>˘</span> <span class='Value'>co</span> <span class='Function'></span><span class='Modifier2'></span><span class='Function'></span> <span class='Value'>ln</span>
┌─                            
╵ ⟨ "Phelps" ⟩                
  ⟨ "Latynina" "Andrianov" ⟩  
  ⟨ "Bjørgen" "Bjørndalen" ⟩  
                             ┘
</pre>
<p>If we would like a particular index to key correspondence, we can use a fixed left argument to <a href="search.html#index-of">Index Of</a>.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Y291bnRyaWVzIOKGkCAiSVQi4oC/IkpQIuKAvyJOTyLigL8iU1Ui4oC/IlVTIgpjb3VudHJpZXMg4omNy5ggY28gY291bnRyaWVz4oq44oqQ4oq44oqUIGxu">↗️</a><pre>    <span class='Value'>countries</span> <span class='Gets'></span> <span class='String'>&quot;IT&quot;</span><span class='Ligature'></span><span class='String'>&quot;JP&quot;</span><span class='Ligature'></span><span class='String'>&quot;NO&quot;</span><span class='Ligature'></span><span class='String'>&quot;SU&quot;</span><span class='Ligature'></span><span class='String'>&quot;US&quot;</span>
    <span class='Value'>countries</span> <span class='Function'></span><span class='Modifier'>˘</span> <span class='Value'>co</span> <span class='Value'>countries</span><span class='Modifier2'></span><span class='Function'></span><span class='Modifier2'></span><span class='Function'></span> <span class='Value'>ln</span>
┌─                                 
╵ "IT" ⟨⟩                          
  "JP" ⟨⟩                          
  "NO" ⟨ "Bjørgen" "Bjørndalen" ⟩  
  "SU" ⟨ "Latynina" "Andrianov" ⟩  
  "US" ⟨ "Phelps" ⟩                
                                  ┘
</pre>
<p>However, this solution will fail if there are trailing keys with no values. To force the result to have a particular length you can append that length to the left argument.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Y291bnRyaWVzIOKGqSAiSVQi4oC/IkpQIuKAvyJOTyLigL8iU1Ui4oC/IlVTIuKAvyJaVyIKY291bnRyaWVzIOKJjcuYIGNvIGNvdW50cmllc+KKuCjiipDiiL7iiaDiiJjiiqMp4oq44oqUIGxu">↗️</a><pre>    <span class='Value'>countries</span> <span class='Gets'></span> <span class='String'>&quot;IT&quot;</span><span class='Ligature'></span><span class='String'>&quot;JP&quot;</span><span class='Ligature'></span><span class='String'>&quot;NO&quot;</span><span class='Ligature'></span><span class='String'>&quot;SU&quot;</span><span class='Ligature'></span><span class='String'>&quot;US&quot;</span><span class='Ligature'></span><span class='String'>&quot;ZW&quot;</span>
    <span class='Value'>countries</span> <span class='Function'></span><span class='Modifier'>˘</span> <span class='Value'>co</span> <span class='Value'>countries</span><span class='Modifier2'></span><span class='Paren'>(</span><span class='Function'>⊐∾≠</span><span class='Modifier2'></span><span class='Function'></span><span class='Paren'>)</span><span class='Modifier2'></span><span class='Function'></span> <span class='Value'>ln</span>
┌─                                 
╵ "IT" ⟨⟩                          
  "JP" ⟨⟩                          
  "NO" ⟨ "Bjørgen" "Bjørndalen" ⟩  
  "SU" ⟨ "Latynina" "Andrianov" ⟩  
  "US" ⟨ "Phelps" ⟩                
  "ZW" ⟨⟩                          
                                  ┘
</pre>
<h3 id="partitioning"><a class="header" href="#partitioning">Partitioning</a></h3>
<p>In examples we have been using a list of strings stranded together. Often it's more convenient to write the string with spaces, and split it up as part of the code. In this case, the index corresponding to each word (that is, each letter in the word) is the number of spaces before it. We can get this number of spaces from a Plus-<a href="scan.html">Scan</a> on the boolean list which is 1 at each space.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=JyAnKCtg4oiYPeKKlOKKoikiQlFOIHVzZXMgbm90YXRpb24gYXMgYSB0b29sIG9mIHRob3VnaHQi">↗️</a><pre>    <span class='String'>' '</span><span class='Paren'>(</span><span class='Function'>+</span><span class='Modifier'>`</span><span class='Modifier2'></span><span class='Function'>=⊔⊢</span><span class='Paren'>)</span><span class='String'>&quot;BQN uses notation as a tool of thought&quot;</span>
⟨ "BQN" " uses" " notation" " as" " a" " tool" " of" " thought" ⟩
</pre>
<p>To avoid including spaces in the result, we should change the result index at each space to ¯1. Here is one way to do that:</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=JyAnKCjiiqIty5zCrMOXK2Ap4oiYPeKKlOKKoikiQlFOIHVzZXMgbm90YXRpb24gYXMgYSB0b29sIG9mIHRob3VnaHQi">↗️</a><pre>    <span class='String'>' '</span><span class='Paren'>((</span><span class='Function'>⊢-</span><span class='Modifier'>˜</span><span class='Function'>¬×+</span><span class='Modifier'>`</span><span class='Paren'>)</span><span class='Modifier2'></span><span class='Function'>=⊔⊢</span><span class='Paren'>)</span><span class='String'>&quot;BQN uses notation as a tool of thought&quot;</span>
⟨ "BQN" "uses" "notation" "as" "a" "tool" "of" "thought" ⟩
</pre>
<p>A function with structural <a href="under.html">Under</a>, such as <code><span class='Brace'>{</span><span class='Number'>¯1</span><span class='Modifier'>¨</span><span class='Modifier2'></span><span class='Paren'>(</span><span class='Value'>𝕩</span><span class='Modifier2'></span><span class='Function'>/</span><span class='Paren'>)</span><span class='Function'>+</span><span class='Modifier'>`</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code>, would also work.</p>
<p>In other cases, we might want to split on spaces, so that words are separated by any number of spaces, and extra spaces don't affect the output. Currently our function makes a new word with each space:</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=JyAnKCjiiqIty5zCrMOXK2Ap4oiYPeKKlOKKoikiICBzdHJpbmcgd2l0aCAgc3BhY2VzICAgIg==">↗️</a><pre>    <span class='String'>' '</span><span class='Paren'>((</span><span class='Function'>⊢-</span><span class='Modifier'>˜</span><span class='Function'>¬×+</span><span class='Modifier'>`</span><span class='Paren'>)</span><span class='Modifier2'></span><span class='Function'>=⊔⊢</span><span class='Paren'>)</span><span class='String'>&quot;  string with  spaces   &quot;</span>
⟨ ⟨⟩ ⟨⟩ "string" "with" ⟨⟩ "spaces" ⟩
</pre>
<p>Trailing spaces are ignored because Group with equal-length arguments never produces trailing empty groups—to intentionally include them you'd replace <code><span class='Function'>=</span></code> with <code><span class='Paren'>(</span><span class='Function'>=∾</span><span class='Number'>0</span><span class='Modifier'>˙</span><span class='Paren'>)</span></code>. But in string processing we probably want to avoid empty words anywhere. To make this happen, we should increase the word index only once per group of spaces. We can do this by applying Plus Scan to a list that is 1 only for a space with no space before it. This list is produced using <a href="shift.html">Shift Before</a> to get a list of previous elements. To treat the first element as though it's before a space (so that leading spaces have no effect rather than creating an initial empty group), we shift in a 1.</p>
<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=KOKKouKJjTHiirjCuzziiqIpICcgJz0iICBzdHJpbmcgd2l0aCAgc3BhY2VzICAgIiAgIyBBbGwsIHRoZW4gZmlsdGVyZWQsIHNwYWNlcwriiY3in5wo4oqiLcucwqzDl8K3K2Ax4oq4wrs84oqiKScgJz0iICBzdHJpbmcgd2l0aCAgc3BhY2VzICAgIiAgIyBNb3JlIHByb2Nlc3NpbmcKJyAnKCjiiqIty5zCrMOXwrcrYDHiirjCuzziiqIp4oiYPeKKlOKKoikiICBzdHJpbmcgd2l0aCAgc3BhY2VzICAgIiAgIyBGaW5hbCByZXN1bHQKCicgJygowqwty5ziiqLDl8K3K2DCu+KKuD4p4oiY4omg4oqU4oqiKSIgIHN0cmluZyB3aXRoICBzcGFjZXMgICAiICAjIFNsaWdodGx5IHNob3J0ZXI=">↗️</a><pre>    <span class='Paren'>(</span><span class='Function'>⊢≍</span><span class='Number'>1</span><span class='Modifier2'></span><span class='Function'>»&lt;</span><span class='Paren'>)</span> <span class='String'>' '</span><span class='Function'>=</span><span class='String'>&quot;  string with  spaces   &quot;</span>  <span class='Comment'># All, then filtered, spaces
</span>┌─                                                 
╵ 1 1 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1  
  0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0  
                                                  ┘
    <span class='Function'></span><span class='Modifier2'></span><span class='Paren'>(</span><span class='Function'>⊢-</span><span class='Modifier'>˜</span><span class='Function'>¬×</span><span class='Nothing'>·</span><span class='Function'>+</span><span class='Modifier'>`</span><span class='Number'>1</span><span class='Modifier2'></span><span class='Function'>»&lt;</span><span class='Paren'>)</span><span class='String'>' '</span><span class='Function'>=</span><span class='String'>&quot;  string with  spaces   &quot;</span>  <span class='Comment'># More processing
</span>┌─                                                         
╵  1  1 0 0 0 0 0 0  1 0 0 0 0  1  1 0 0 0 0 0 0  1  1  1  
  ¯1 ¯1 0 0 0 0 0 0 ¯1 1 1 1 1 ¯1 ¯1 2 2 2 2 2 2 ¯1 ¯1 ¯1  
                                                          ┘
    <span class='String'>' '</span><span class='Paren'>((</span><span class='Function'>⊢-</span><span class='Modifier'>˜</span><span class='Function'>¬×</span><span class='Nothing'>·</span><span class='Function'>+</span><span class='Modifier'>`</span><span class='Number'>1</span><span class='Modifier2'></span><span class='Function'>»&lt;</span><span class='Paren'>)</span><span class='Modifier2'></span><span class='Function'>=⊔⊢</span><span class='Paren'>)</span><span class='String'>&quot;  string with  spaces   &quot;</span>  <span class='Comment'># Final result
</span>⟨ "string" "with" "spaces" ⟩

    <span class='String'>' '</span><span class='Paren'>((</span><span class='Function'>¬-</span><span class='Modifier'>˜</span><span class='Function'>⊢×</span><span class='Nothing'>·</span><span class='Function'>+</span><span class='Modifier'>`</span><span class='Function'>»</span><span class='Modifier2'></span><span class='Function'>&gt;</span><span class='Paren'>)</span><span class='Modifier2'></span><span class='Function'>≠⊔⊢</span><span class='Paren'>)</span><span class='String'>&quot;  string with  spaces   &quot;</span>  <span class='Comment'># Slightly shorter
</span>⟨ "string" "with" "spaces" ⟩
</pre>