requires: {#ExtensibleCollection. #Dictionary. #Method. #Set. #ExtensibleArray}. provides: {#Grouping. #SequentialGrouping}. collections addPrototype: #Grouping derivedFrom: {ExtensibleCollection}. "Similar to a Bag, storing elements given into bins keyed by the result of applying a block to each." Grouping addSlot: #contents valued: Dictionary newEmpty. Grouping addSlot: #attributeBlock valued: Method Identity. g@(Grouping traits) newSize: n [| newG | newG: g clone. newG contents: (g contents newSize: n). newG ]. c@(Collection traits) grouped [c groupedBy: Method Identity]. c@(Collection traits) groupedBy: keyBlock [| newG | newG: Grouping newEmpty. newG attributeBlock: keyBlock. newG addAll: c. newG ]. g@(Grouping traits) add: obj [| key group | key: (g attributeBlock applyWith: obj). group: (g contents at: key ifAbsent: [g contents at: key put: Set newEmpty]). group include: obj. obj ]. g@(Grouping traits) remove: obj [| key | key: (g attributeBlock applyWith: obj). group: (g contents at: key ifAbsent: [^ obj]). group remove: obj. group isEmpty ifTrue: [g contents removeKey: key]. obj ]. collections addPrototype: #SequentialGrouping derivedFrom: {Grouping}. "A Grouping that preserves the order of an original sequential ordering (whether from a WriteStream on the Grouping or an actual Sequence)." s@(Sequence traits) groupedBy: keyBlock [| newG | newG: SequentialGrouping newEmpty. newG attributeBlock: keyBlock. newG addAll: c. newG ]. g@(Grouping traits) add: obj [| key group | key: (g attributeBlock applyWith: obj). group: (g contents at: key ifAbsent: [g contents at: key put: ExtensibleArray newEmpty]). group include: obj. obj ].