Search code examples
arrayssmalltalkpharoidioms

What's the idiomatic way to split a Smalltalk array at the spot where a series of values changes?


Given an array of domain objects (with the properties subject, trial and run) like this:

+---------+-------+-----+
| Subject | Trial | Run |
+---------+-------+-----+
|       1 |     1 |   1 |
|       1 |     2 |   1 |
|       1 |     3 |   2 |
|       1 |     4 |   2 |
|       2 |     1 |   1 |
|       2 |     2 |   1 |
|       1 |     1 |   1 |
|       1 |     2 |   1 |
+---------+-------+-----+

i want to split it into multiple arrays at every point where the value for subject changes.
The above example should result in three arrays:

+---------+-------+-----+
| Subject | Trial | Run |
+---------+-------+-----+
|       1 |     1 |   1 |
|       1 |     2 |   1 |
|       1 |     3 |   2 |
|       1 |     4 |   2 |
+---------+-------+-----+

+---------+-------+-----+
|       2 |     1 |   1 |
|       2 |     2 |   1 |
+---------+-------+-----+

+---------+-------+-----+
|       1 |     1 |   1 |
|       1 |     2 |   1 |
+---------+-------+-----+

What would be the idiomatic Smalltalk (Pharo) way to split the array like this?


Solution

  • SequenceableCollection >> piecesCutWhere: which takes a binary block is your friend:

    { 1. 1. 2. 2. 2. 3. 1. 2. } piecesCutWhere: [:left :right | left ~= right]
    => an OrderedCollection #(1 1) #(2 2 2) #(3) #(1) #(2)