SeqColl.st
changeset 61 f8c30e686fbf
parent 44 b262907c93ea
child 69 4564b6328136
--- a/SeqColl.st	Fri Feb 25 14:03:36 1994 +0100
+++ b/SeqColl.st	Fri Feb 25 14:03:58 1994 +0100
@@ -26,7 +26,7 @@
 an index. SequenceableCollection is an abstract class - there are no
 instances of it in the system.
 
-$Header: /cvs/stx/stx/libbasic/Attic/SeqColl.st,v 1.8 1994-01-16 03:45:26 claus Exp $
+$Header: /cvs/stx/stx/libbasic/Attic/SeqColl.st,v 1.9 1994-02-25 13:03:42 claus Exp $
 
 written spring 89 by claus
 '!
@@ -59,8 +59,9 @@
 !
 
 at:index ifAbsent:exceptionBlock
-    "return the element at index if valid. If the index is invalid,
-     return the result of evaluating the exceptionblock"
+    "return the element at index if valid. 
+     If the index is invalid, return the result of evaluating 
+     the exceptionblock."
 
     ((index < 1) or:[index > self size]) ifTrue:[
         ^ exceptionBlock value
@@ -68,6 +69,8 @@
     ^ self at:index
 
     "#(1 2 3) at:4 ifAbsent:['no such index']"
+    "(Dictionary with:(#foo -> #bar)
+                 with:(#frob -> #baz)) at:#foobar ifAbsent:['no such index']"
 ! !
 
 !SequenceableCollection methodsFor:'queries'!
@@ -105,6 +108,7 @@
 
     stop := self size.
     stop == (aCollection size) ifFalse:[^false].
+
     index := 1.
     [index <= stop] whileTrue:[
         (self at:index) = (aCollection at:index) ifFalse:[^false].
@@ -149,18 +153,20 @@
 
     |index1 "{ Class: SmallInteger }"
      index2 "{ Class: SmallInteger }" 
-     stop   "{ Class: SmallInteger }" |
+     stop   "{ Class: SmallInteger }" 
+     sz     "{ Class: SmallInteger }"|
 
-    (aCollection == self) ifTrue:[^true].
-    (aCollection isKindOf:SequenceableCollection) ifFalse:[^false].
+    (aCollection == self) ifTrue:[^ true].
+    (aCollection isKindOf:SequenceableCollection) ifFalse:[^ false].
 
     stop := aCollection size.
-    stop > self size ifTrue:[^false].
+    sz := self size.
+    stop > sz ifTrue:[^false].
 
-    index1 := self size.
+    index1 := sz.
     index2 := stop.
     [index2 > 0] whileTrue:[
-        (self at:index1) = (aCollection at:index2) ifFalse:[^false].
+        (self at:index1) = (aCollection at:index2) ifFalse:[^ false].
         index1 := index1 - 1.
         index2 := index2 - 1
     ].
@@ -211,10 +217,11 @@
     "'abc' , '123'"
     "'abc' , #($q $w $e $r $t $y) asSortedCollection"
     "'abc' , #(1 2 3 4 5)"  "-- will fail, since strings cannot store integers"
+    "'abc' asArray , #(1 2 3 4 5)"
 !
 
 copyWith:newElement
-    "return a new collection consisting of receivers elements
+    "return a new collection consisting of a copy of the receivers elements
      plus the argument."
 
     |newCollection mySize newSize|
@@ -232,10 +239,10 @@
     "'abcdefg' copyWith:1"      "-- will fail: integer cannot be stored into string"
 !
 
-copyWithout:elementToSkip
-    "return a new collection consisting of receivers elements
-     without elementToSkip, if it was present. No error is reported,
-     if elementToSkip is not in the collection."
+copyWithoutFirst:elementToSkip
+    "return a new collection consisting of a copy of the receivers elements
+     without the first elementToSkip, if it was present. 
+     No error is reported, if elementToSkip is not in the collection."
 
     |copy skipIndex sz|
 
@@ -248,9 +255,76 @@
     copy replaceFrom:skipIndex to:(sz - 1) with:self startingAt:(skipIndex + 1).
     ^ copy
 
+    "#($a $b $c $d $e $f $g) copyWithoutFirst:$d"
+    "#($a $b $c $d $e $f $g) copyWithoutFirst:$x"
+    "#(90 80 70 60 50) copyWithoutFirst:70"
+    "#(90 80 70 80 60 45 80 50) copyWithoutFirst:80"
+!
+
+copyWithout:elementToSkip
+    "return a new collection consisting of a copy of the receiver, with
+     ALL elements equal to elementToSkip are left out.
+     No error is reported, if elementToSkip is not in the collection."
+
+    |n copy srcIndex dstIndex skipIndex sz l|
+
+    "the code below may look like overkill, 
+     however, for big collections its better to move data
+     around in big chunks"
+
+    n := self occurrencesOf:elementToSkip.
+    n == 0 ifTrue:[^ self copy].
+
+    sz := self size.
+    copy := self species new:(sz - n).
+
+    srcIndex := 1.
+    dstIndex := 1.
+
+    n timesRepeat:[
+        skipIndex := self indexOf:elementToSkip startingAt:srcIndex.
+        l := skipIndex - srcIndex.
+        l ~~ 0 ifTrue:[
+            copy replaceFrom:dstIndex to:(dstIndex + l - 1) 
+                        with:self startingAt:srcIndex.
+            dstIndex := dstIndex + l
+        ].
+        srcIndex := skipIndex + 1
+    ].
+    l := sz - srcIndex.
+    copy replaceFrom:dstIndex to:(dstIndex + l)
+                with:self startingAt:srcIndex.
+    ^ copy
+
     "#($a $b $c $d $e $f $g) copyWithout:$d"
+    "#($a $b $c $d $e $f $g) copyWithout:$a"
+    "#($a $b $c $d $e $f $g) copyWithout:$g"
+    "#($a $b $c $a $a $d $e $a $f $g) copyWithout:$a"
     "#($a $b $c $d $e $f $g) copyWithout:$x"
-    "#(90 80 70 60 50) asSortedCollection copyWithout:70"
+    "#(90 80 70 60 50) copyWithout:70"
+    "#(90 80 70 80 60 45 80 50) copyWithout:80"
+!
+
+copyWithoutIndex:omitIndex
+    "return a new collection consisting of receivers elements
+     without the argument stored at omitIndex"
+
+    |copy sz|
+
+    sz := self size.
+    copy := self species new:(sz - 1).
+    copy replaceFrom:1 
+                  to:(omitIndex - 1) 
+                with:self 
+          startingAt:1.
+    copy replaceFrom:omitIndex 
+                  to:sz - 1 
+                with:self 
+          startingAt:(omitIndex + 1).
+    ^ copy
+
+    "#(1 2 3 4 5 6 7 8 9 0) copyWithoutIndex:3"
+    "'abcdefghijkl' copyWithoutIndex:5"
 !
 
 copyFrom:start to:stop
@@ -260,7 +334,7 @@
     |newCollection newSize|
 
     newSize := stop - start + 1.
-    newCollection := self class new:newSize.
+    newCollection := self species new:newSize.
     newCollection replaceFrom:1 to:newSize with:self startingAt:start.
     ^ newCollection
 
@@ -280,7 +354,7 @@
 
 copyTo:stop
     "return a new collection consisting of receivers elements
-     from 1 up to index stop"
+     from 1 up to (including) index stop"
 
     ^ self copyFrom:1 to:stop
 
@@ -288,21 +362,82 @@
     "'1234567890' copyTo:4"
 !
 
-copyWithoutIndex:omitIndex
-    "return a new collection consisting of receivers elements
-     without the argument stored at omitIndex"
+copyFirst:count
+    "return a new collection consisting of the receivers first count
+     elements - this is just a rename of copyTo: - for compatibility."
+
+    ^ self copyFrom:1 to:count
+
+    "#($a $b $c $d $e $f $g) copyFirst:5"
+    "'1234567890' copyFirst:4"
+!
+
+copyLast:count
+    "return a new collection consisting of the receivers last count
+     elements."
+
+    |sz|
 
-    |copy|
+    sz := self size.
+    ^ self copyFrom:(sz - count + 1) to:sz
+
+    "#($a $b $c $d $e $f $g) copyLast:5"
+    "'1234567890' copyLast:4"
+!
+
+copyUpTo:element
+    "return a new collection consisting of the receiver elements
+     up-to (but excluding) the first occurence of element."
+
+    |idx|
+
+    idx := self indexOf:element.
+    idx == 0 ifTrue:[^ nil].    "question: is this ok?"
+    idx == 1 ifTrue:[^ self species new].
+    ^ self copyFrom:1 to:(idx-1)
 
-    copy := self class new:(self size - 1).
-    copy replaceFrom:1 to:(omitIndex - 1) with:self startingAt:1.
-    copy replaceFrom:omitIndex to:(copy size) 
-                with:self startingAt:(omitIndex + 1).
-    ^ copy
+    "#($a $b $c $d $e $f $g) copyUpTo:$d"
+    "'1234567890' copyUpTo:$5"
+    "'1234567890' copyUpTo:$a"
+    "'1234567890' copyUpTo:$1"
+!
+
+copyThrough:element
+    "return a new collection consisting of the receiver elements
+     up-to (AND including) the first occurence of element."
+
+    |idx|
+
+    idx := self indexOf:element.
+    idx == 0 ifTrue:[^ nil].    "question: is this ok?"
+    ^ self copyFrom:1 to:idx
 
-    "#(1 2 3 4 5 6 7 8 9 0) copyWithoutIndex:3"
-    "'abcdefghijkl' copyWithoutIndex:5"
+    "#($a $b $c $d $e $f $g) copyThrough:$d"
+    "'1234567890' copyThrough:$5"
+    "'1234567890' copyThrough:$a"
+    "'1234567890' copyThrough:$1"
+!
+
+copyReplaceFrom:startIndex to:endIndex with:aCollection
+    "return a copy of the receiver, where the elements from startIndex to
+     endIndex have been replaced by the elements of aCollection"
+
+    |newColl replSize|
 
+    replSize := aCollection size.
+    newColl := self species new:(self size - (endIndex - startIndex + 1) + replSize).
+    newColl replaceFrom:1 to:(startIndex - 1) with:self.
+    newColl replaceFrom:startIndex with:aCollection.
+    newColl replaceFrom:(startIndex + replSize) with:self startingAt:(endIndex + 1).
+    ^ newColl
+
+    "#(1 2 3 4 5 6 7 8 9 0) copyReplaceFrom:3 to:6 with:#(a b c d e f g h i j k)"
+    "'hello world' copyReplaceFrom:6 to:6 with:' there, '"
+!
+
+copyReplaceAll:startIndex to:endIndex with:aCollection
+    "return a copy of the receiver, where the elements from startIndex to
+     endIndex have been replaced by the elements of aCollection"
 ! !
 
 !SequenceableCollection methodsFor:'filling and replacing'!
@@ -403,6 +538,9 @@
                     to:stop
                   with:replacementCollection
             startingAt:1
+
+    "'1234567890' replaceFrom:5 to:7 with:'abcdef'"
+    "#($a $b $c $d $e) replaceFrom:2 to:3 with:'12345'"
 !
 
 replaceFrom:start to:stop with:replacementCollection startingAt:repStart
@@ -438,6 +576,24 @@
         srcIndex := srcIndex + 1.
         dstIndex := dstIndex + 1
     ]
+
+    "'1234567890' replaceFrom:5 to:7 with:'abcdef' startingAt:3"
+    "#($a $b $c $d $e) replaceFrom:2 to:3 with:'12345' startingAt:4"
+!
+
+startingAt:sourceStart replaceElementsIn:destColl from:destStartIndex to:destEndIndex
+    "replace elements in destColl with elements from the receiver.
+     Notice: This operation modifies the destination collection, NOT a copy;
+     therefore the change may affect all others referencing this object."
+
+    destColl replaceFrom:destStartIndex to:destEndIndex with:self startingAt:sourceStart
+
+    "
+     |s|
+     s := 'abcdefghijklmnop'.
+     '1234567890' startingAt:1 replaceElementsIn:s from:1 to:3.
+     s'123defghijklmnop'
+    "
 !
 
 withCRs
@@ -460,33 +616,72 @@
 
 !SequenceableCollection methodsFor:'adding & removing'!
 
-addFirst:anElement
-    "prepend the argument, anElement to the collection."
+addFirst:anObject
+    "prepend the argument, anObject to the collection.
+     Return the argument, anObject.
+
+     Notice, that this is modifies the receiver NOT a copy.
+     Also note, that it may be a slow operation for some collections due to the grow: 
+     (i.e. for Strings and Arrays it is not recommened)"
 
     |newSize|
 
     newSize := self size + 1.
     self grow:newSize.
     self replaceFrom:2 to:newSize with:self startingAt:1.
-    self at:1 put:anElement
+    self at:1 put:anObject.
+    ^ anObject
 
-    "#(1 2 3 4 5 6 7 8) addFirst:'hello'"
+    "
+     |a| 
+     a:= #(1 2 3 4 5 6 7 8). 
+     a addFirst:'hello'. 
+     a
+    "
+    "
+     |c|
+     c := #(1 2 3 4 5 6 7 8) asOrderedCollection.
+     c addFirst:'hello'.
+     c
+    "
 !
 
-add:anElement
-    "append the argument, anElement to the collection"
+add:anObject
+    "append the argument, anObject to the collection.
+     Return the argument, anObject.
+
+     Notice, that this is modifies the receiver NOT a copy.
+     Also note, that it may be a slow operation for some collections due to the grow: 
+     (i.e. for Strings and Arrays it is not recommened)"
 
     |newSize|
 
     newSize := self size + 1.
     self grow:newSize.
-    self at:newSize put:anElement
+    self at:newSize put:anObject.
+    ^ anObject
 
-    "#(1 2 3 4 5 6 7 8) add:'hello'"
+    "
+     |a|
+     a := #(1 2 3 4 5 6 7 8).
+     a add:'hello'.
+     a
+    "
+    "
+     |c|
+     c := #(1 2 3 4 5 6 7 8) asOrderedCollection.
+     c add:'hello'.
+     c
+    "
 !
 
 add:anElement beforeIndex:index
-    "insert the first argument, anObject into the collection before slot index"
+    "insert the first argument, anObject into the collection before slot index.
+     Return the receiver (sigh - ST-80 compatibility).
+
+     Notice, that this is modifies the receiver NOT a copy.
+     Also note, that it may be a slow operation for some collections due to the grow: 
+     (i.e. for Strings and Arrays it is not recommened)"
 
     |newSize|
 
@@ -499,8 +694,12 @@
 !
 
 remove:anElement ifAbsent:aBlock
-    "search for anElement and, if present remove it; if not present
-     return the value of evaluating aBlock"
+    "search for anElement and, if present remove and return it.
+     If not present, return the value of evaluating aBlock.
+
+     Notice, that this is modifies the receiver NOT a copy.
+     Also note, that it may be a slow operation for some collections due to the grow: 
+     (i.e. for Strings and Arrays it is not recommened)"
 
     |any 
      dstIndex "{ Class: SmallInteger }"
@@ -520,17 +719,21 @@
         ]
     ].
     any ifTrue:[
-        self grow:dstIndex - 1
-    ] ifFalse:[
-        aBlock value
-    ]
+        self grow:dstIndex - 1.
+        ^ anElement
+    ].
+    ^ aBlock value
 
     "#(1 2 3 4 5 6 7 8 9 0) remove:3 ifAbsent:[Transcript showCr:'no']"
-    "#(1 2 3 4 5 6 7 8 9 0) remove:99 ifAbsent:[Transcript showCr:'no']"
+    "#(1 2 3 4 5 6 7 8 9 0) remove:99 ifAbsent:[#oops]"
 !
 
 removeFromIndex:startIndex toIndex:endIndex
-    "remove the elements stored at indexes between startIndex and endIndex"
+    "remove the elements stored at indexes between startIndex and endIndex.
+
+     Notice, that this is modifies the receiver NOT a copy.
+     Also note, that it may be a slow operation for some collections due to the grow: 
+     (i.e. for Strings and Arrays it is not recommened)"
 
     |newSize|
 
@@ -541,12 +744,66 @@
     "#(1 2 3 4 5 6 7 8 9 0) removeFromIndex:3 toIndex:5"
 !
 
+removeAtIndex:index
+    "remove the argument stored at index and return it.
+
+     Notice, that this is modifies the receiver NOT a copy.
+     Also note, that it may be a slow operation for some collections due to the grow: 
+     (i.e. for Strings and Arrays it is not recommened)"
+
+    |element|
+
+    element := self at:index.
+    self removeIndex:index.
+    ^ element
+
+    "#($a $b $c $d $e $f $g) removeAtIndex:3"
+!
+
 removeIndex:index
-    "remove the argument stored at index"
+    "remove the argument stored at index. Return the receiver.
+
+     Notice, that this is modifies the receiver NOT a copy.
+     Also note, that it may be a slow operation for some collections due to the grow: 
+     (i.e. for Strings and Arrays it is not recommened)"
 
     self removeFromIndex:index toIndex:index
 
-    "#(1 2 3 4 5 6 7 8 9 0) removeIndex:3"
+    "#($a $b $c $d $e $f $g) removeIndex:3"
+!
+
+removeFirst
+    "remove the first element of the receiver and return it.
+
+     Notice, that this is modifies the receiver NOT a copy.
+     Also note, that it may be a slow operation for some collections due to the grow: 
+     (i.e. for Strings and Arrays it is not recommened)"
+
+    ^ self removeAtIndex:1
+
+    "
+    |a|
+     a := #(1 2 3 4 5 6).
+     a removeFirst.
+     a
+    "
+!
+
+removeLast
+    "remove the last element of the receiver and return it.
+
+     Notice, that this is modifies the receiver NOT a copy.
+     Also note, that it may be a slow operation for some collections due to the grow: 
+     (i.e. for Strings and Arrays it is not recommened)"
+
+    ^ self removeAtIndex:(self size) 
+
+    "
+    |a|
+     a := #(1 2 3 4 5 6).
+     a removeLast.
+     a
+    "
 ! !
 
 !SequenceableCollection methodsFor:'searching'!