+asCollectionOfSubCollectionsSeparatedBy*
authorClaus Gittinger <cg@exept.de>
Tue, 19 Apr 2005 11:05:46 +0200
changeset 8851 3910c013402b
parent 8850 b9a04c753bfa
child 8852 9f5984eff2c2
+asCollectionOfSubCollectionsSeparatedBy*
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!