Skip to content
A library to group collections on an arbitrary number of levels for Pharo.
Smalltalk HTML
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src
.project Added grouper package. Aug 21, 2019
.smalltalk.ston Set up continuous integration. Aug 21, 2019
.travis.yml Set up continuous integration. Aug 21, 2019
LICENSE
README.md Update README.md Aug 26, 2019

README.md

Grouper

Build Status License Pharo version Pharo version

A library to group collections on an arbitrary number of levels for Pharo.

Install

Metacello new
  repository: 'github://juliendelplanque/Grouper/src';
  baseline: 'Grouper';
  load

Examples

Getting started

The following code snippet using Grouper:

(10 to: 50) groupUsing: [ :integer | integer asString first ].
"an OrderedDictionary(
  $1->#(10 11 12 13 14 15 16 17 18 19)
  $2->#(20 21 22 23 24 25 26 27 28 29)
  $3->#(30 31 32 33 34 35 36 37 38 39)
  $4->#(40 41 42 43 44 45 46 47 48 49)
  $5->#(50))"

is equivalent to the following code snippet using built-in #groupedBy: method:

(10 to: 50) groupedBy: [ :integer | integer asString first ]
"an OrderedDictionary(
  $1->#(10 11 12 13 14 15 16 17 18 19)
  $2->#(20 21 22 23 24 25 26 27 28 29)
  $3->#(30 31 32 33 34 35 36 37 38 39)
  $4->#(40 41 42 43 44 45 46 47 48 49)
  $5->#(50))"

The power of Grouper is that group description are first-class objects. Thus, it is possible to compose group descriptions in order to group a flat collection on multiple levels.

For example:

groupComposition := [ :integer | integer asString first ] grouper , [ :integer | integer asString second ].
(10 to: 50) groupUsing: groupComposition.
"an OrderedDictionary(
  $1->an OrderedDictionary(
    $0->#(10) $1->#(11) $2->#(12) $3->#(13) $4->#(14) $5->#(15) $6->#(16) $7->#(17) $8->#(18) $9->#(19))
  $2->an OrderedDictionary(
    $0->#(20) $1->#(21) $2->#(22) $3->#(23) $4->#(24) $5->#(25) $6->#(26) $7->#(27) $8->#(28) $9->#(29))
  $3->an OrderedDictionary(
    $0->#(30) $1->#(31) $2->#(32) $3->#(33) $4->#(34) $5->#(35) $6->#(36) $7->#(37) $8->#(38) $9->#(39))
  $4->an OrderedDictionary(
    $0->#(40) $1->#(41) $2->#(42) $3->#(43) $4->#(44) $5->#(45) $6->#(46) $7->#(47) $8->#(48) $9->#(49))
  $5->an OrderedDictionary($0->#(50)))"

Building a tree

In fact, Grouper builds a tree. By default, it uses dictionaries for its nodes and the initial object in the collection for its leaves.

Grouper provides the ability to customize the kind of objects the tree is built of. This is achived via #leafCollect:, #nodeCollect: and #wrapRoot:.

#leafCollect:

#leafCollect: allows one to customize the objects that will appear as leaves in the tree. It is used as follow:

grouper := [ :integer | integer asString first ] grouper , [ :integer | integer asString second ] grouper.

grouper leafCollect: [ :result | GTreeLeafMock new content: result; yourself ]. 

(10 to: 15) groupUsing: groupComposition.
"an OrderedDictionary(
  $1->an OrderedDictionary(
    $0->an Array(a GTreeLeafMock)
    $1->an Array(a GTreeLeafMock)
    $2->an Array(a GTreeLeafMock)
    $3->an Array(a GTreeLeafMock)
    $4->an Array(a GTreeLeafMock)
    $5->an Array(a GTreeLeafMock)))"

#nodeCollect:

#nodeCollect: allows one to customize the objects that will appear as nodes in the tree. It is used as follow:

groupComposition := [ :integer | integer asString first ] grouper , [ :integer | integer asString second ] grouper.

groupComposition nodeCollect: [ :dictionary |
	dictionary associations collect: [ :association |
		GTreeNodeMock new
			content: association key;
			children: association value
			yourself ] ]. 

(10 to: 15) groupUsing: groupComposition.
"an Array(a GTreeNodeMock)"

#rootWrap:

#rootWrap: allows one to customize the object used to wrap the tree at its root. It is used as follow:

groupComposition := [ :integer | integer asString first ] grouper , [ :integer | integer asString second ] grouper.
	
groupComposition rootWrap: [ :array | GTreeRoot new children: array; yourself ].

(10 to: 15) groupUsing: groupComposition.
 "a GTreeRoot"
You can’t perform that action at this time.