# HG changeset patch # User Claus Gittinger # Date 1113901546 -7200 # Node ID 3910c013402b609386f6ff88ff96fec18d6f39a3 # Parent b9a04c753bfa1faafadf1f62bdbe7f52d37c6680 +asCollectionOfSubCollectionsSeparatedBy* diff -r b9a04c753bfa -r 3910c013402b SequenceableCollection.st --- a/SequenceableCollection.st Mon Apr 18 21:54:23 2005 +0200 +++ b/SequenceableCollection.st Tue Apr 19 11:05:46 2005 +0200 @@ -1692,6 +1692,146 @@ !SequenceableCollection methodsFor:'converting'! +asCollectionOfSubCollectionsSeparatedBy:anElement + "return a collection containing the subcollections (separated by anElement) + of the receiver. If anElement occurs multiple times in a row, + the result will contain empty collections. + This algorithm uses equality-compare to detect the element." + + |cols myClass + numberOfCols "{ Class:SmallInteger }" + startIndex "{ Class:SmallInteger }" + stopIndex "{ Class:SmallInteger }" | + + " + count first, to avoid regrowing of the OC + " + numberOfCols := (self occurrencesOf:anElement) + 1. + cols := OrderedCollection new:numberOfCols. + myClass := self species. + + startIndex := 1. + 1 to:numberOfCols do:[:lineNr | + stopIndex := self indexOf:anElement startingAt:startIndex. + stopIndex == 0 ifTrue:[ + stopIndex := self size + ] ifFalse: [ + stopIndex := stopIndex - 1. + ]. + + (stopIndex < startIndex) ifTrue: [ + cols add:(myClass new:0) + ] ifFalse: [ + cols add:(self copyFrom:startIndex to:stopIndex) + ]. + startIndex := stopIndex + 2 + ]. + ^ cols + + " + '1 one:2 two:3 three:4 four:5 five' withCRs asCollectionOfSubCollectionsSeparatedBy:$: + '1 one 2 two 3 three 4 four 5 five' withCRs asCollectionOfSubCollectionsSeparatedBy:Character space + #(a b c d e f g h) asCollectionOfSubCollectionsSeparatedBy: #d. + #(a b c d e f d d g h) asCollectionOfSubCollectionsSeparatedBy: #d. + " +! + +asCollectionOfSubCollectionsSeparatedByAll:aSeparatorCollection + "return a collection containing the subcollections (separated by aSeparatorCollection) + of the receiver. If aSeparatorCollection occurs multiple times in a row, + the result will contain empty strings. + Uses equality-compare when searching for aSeparatorCollection." + + |items done myClass + startIndex "{ Class:SmallInteger }" + stopIndex "{ Class:SmallInteger }" | + + items := OrderedCollection new. + myClass := self species. + + startIndex := 1. + done := false. + [done] whileFalse:[ + stopIndex := self indexOfSubCollection:aSeparatorCollection startingAt:startIndex. + stopIndex == 0 ifTrue:[ + stopIndex := self size. + done := true. + ] ifFalse: [ + stopIndex := stopIndex - 1. + ]. + + (stopIndex < startIndex) ifTrue: [ + items add:(myClass new:0) + ] ifFalse: [ + items add:(self copyFrom:startIndex to:stopIndex) + ]. + startIndex := stopIndex + (aSeparatorCollection size) + 1. + ]. + ^ items + + " + '1::2::3::4::5::' asCollectionOfSubCollectionsSeparatedByAll:'::' + #(1 2 3 1 2 3 4 3 1 1 2 3 1 4 5) asCollectionOfSubCollectionsSeparatedByAll:#(3 1) + " +! + +asCollectionOfSubCollectionsSeparatedByAny:aCollectionOfSeparators + "return a collection containing the subCollection + (separated by any from aCollectionOfSeparators) of the receiver. + This allows breaking up strings using a number of elements as separator. + Uses equality-compare when searching for separators." + + ^ self asCollectionOfSubCollectionsSeparatedByAnyForWhich:[:el | aCollectionOfSeparators includes:el] + + " + 'hello:world:isnt:this nice' asCollectionOfSubCollectionsSeparatedByAny:#($:) + 'hello:world:isnt:this nice' asCollectionOfSubCollectionsSeparatedByAny:':' + 'hello:world:isnt:this nice' asCollectionOfSubCollectionsSeparatedByAny:(Array with:$: with:Character space) + 'hello:world:isnt:this nice' asCollectionOfSubCollectionsSeparatedByAny:': ' + 'h1e2l3l4o' asCollectionOfSubCollectionsSeparatedByAny:($1 to: $9) + #(1 9 2 8 3 7 4 6 5 5) asCollectionOfSubCollectionsSeparatedByAny:#(1 2 3) + " +! + +asCollectionOfSubCollectionsSeparatedByAnyForWhich:aBlock + "return a collection containing the subCollection + (separated by elements for which aBlock evaluates to true) of the receiver. + This allows breaking up strings using an arbitrary condition." + + |words + start "{ Class:SmallInteger }" + stop "{ Class:SmallInteger }" + mySize "{ Class:SmallInteger }"| + + words := OrderedCollection new. + start := 1. + mySize := self size. + [start <= mySize] whileTrue:[ + "skip multiple separators" + [ aBlock value:(self at:start)] whileTrue:[ + start := start + 1 . + start > mySize ifTrue:[ + ^ words + ]. + ]. + + stop := self findFirst:aBlock startingAt:start. + stop == 0 ifTrue:[ + words add:(self copyFrom:start to:mySize). + ^ words + ]. + words add:(self copyFrom:start to:(stop - 1)). + start := stop + ]. + ^ words + + " + 'hello:world:isnt:this nice' asCollectionOfSubCollectionsSeparatedByAnyForWhich:[:ch | ch = $:] + 'h1e2l3l4o' asCollectionOfSubCollectionsSeparatedByAnyForWhich:[:ch | ch isDigit] + #(1 9 2 8 3 7 4 6 5 5) asCollectionOfSubCollectionsSeparatedByAnyForWhich:[:n | n odd] + " +! + asSequenceableCollection "return myself as a SequenceableCollection. I am already a SequenceableCollection." @@ -6671,7 +6811,7 @@ !SequenceableCollection class methodsFor:'documentation'! version - ^ '$Header: /cvs/stx/stx/libbasic/SequenceableCollection.st,v 1.221 2005-04-08 22:55:22 stefan Exp $' + ^ '$Header: /cvs/stx/stx/libbasic/SequenceableCollection.st,v 1.222 2005-04-19 09:05:46 cg Exp $' ! ! SequenceableCollection initialize!