SeqColl.st
changeset 1 a27a279701f8
child 2 6526dde5f3ac
equal deleted inserted replaced
0:aa2498ef6470 1:a27a279701f8
       
     1 "
       
     2  COPYRIGHT (c) 1989-93 by Claus Gittinger
       
     3               All Rights Reserved
       
     4 
       
     5  This software is furnished under a license and may be used
       
     6  only in accordance with the terms of that license and with the
       
     7  inclusion of the above copyright notice.   This software may not
       
     8  be provided or otherwise made available to, or used by, any
       
     9  other person.  No title to or ownership of the software is
       
    10  hereby transferred.
       
    11 "
       
    12 
       
    13 Collection subclass:#SequenceableCollection
       
    14        instanceVariableNames:''
       
    15        classVariableNames:''
       
    16        poolDictionaries:''
       
    17        category:'Collections-Abstract'
       
    18 !
       
    19 
       
    20 SequenceableCollection comment:'
       
    21 
       
    22 COPYRIGHT (c) 1989-93 by Claus Gittinger
       
    23               All Rights Reserved
       
    24 
       
    25 SequenceableCollections have ordered elements which can be accessed via
       
    26 an index. SequenceableCollection is an abstract class - there are no
       
    27 instances of it in the system.
       
    28 
       
    29 %W% %E%
       
    30 
       
    31 written spring 89 by claus
       
    32 '!
       
    33 
       
    34 !SequenceableCollection class methodsFor:'instance creation'!
       
    35 
       
    36 new:size withAll:element
       
    37     "return a new Collection of size, where all elements are
       
    38      initialized to element"
       
    39 
       
    40     |newCollection|
       
    41 
       
    42     newCollection := self new:size.
       
    43     newCollection atAllPut:element.
       
    44     ^ newCollection
       
    45 ! !
       
    46 
       
    47 !SequenceableCollection methodsFor:'accessing'!
       
    48 
       
    49 first
       
    50     "return the first element"
       
    51 
       
    52     ^ self at:1
       
    53 !
       
    54 
       
    55 last
       
    56     "return the last element"
       
    57 
       
    58     ^ self at:(self size)
       
    59 ! !
       
    60 
       
    61 !SequenceableCollection methodsFor:'comparing'!
       
    62 
       
    63 = aCollection
       
    64     "return true if the receiver and aCollection represent collections
       
    65      with equal contents."
       
    66 
       
    67     |index "{ Class: SmallInteger }"
       
    68      stop  "{ Class: SmallInteger }" |
       
    69 
       
    70     (aCollection == self) ifTrue:[^true].
       
    71     (aCollection isKindOf:SequenceableCollection) ifFalse:[^false].
       
    72 
       
    73     stop := self size.
       
    74     stop == (aCollection size) ifFalse:[^false].
       
    75     index := 1.
       
    76     [index <= stop] whileTrue:[
       
    77         (self at:index) = (aCollection at:index) ifFalse:[^false].
       
    78         index := index + 1
       
    79     ].
       
    80     ^ true
       
    81 !
       
    82 
       
    83 startsWith:aCollection
       
    84     "return true, if the receivers first elements match those
       
    85      of aCollection"
       
    86 
       
    87     |index "{ Class: SmallInteger }"
       
    88      stop  "{ Class: SmallInteger }" |
       
    89 
       
    90     (aCollection == self) ifTrue:[^true].
       
    91     (aCollection isKindOf:SequenceableCollection) ifFalse:[^false].
       
    92 
       
    93     stop := aCollection size.
       
    94     stop > self size ifTrue:[^false].
       
    95 
       
    96     index := 1.
       
    97     [index <= stop] whileTrue:[
       
    98         (self at:index) = (aCollection at:index) ifFalse:[^false].
       
    99         index := index + 1
       
   100     ].
       
   101     ^ true
       
   102 
       
   103     "'abcde' startsWith:#($a $b $c)"
       
   104     "#[1 2 3 4] startsWith:#(1 2 3)"
       
   105     "#(1 2 3 4) asOrderedCollection startsWith:#(1 2 3)"
       
   106 !
       
   107 
       
   108 endsWith:aCollection
       
   109     "return true, if the receivers last elements match those
       
   110      of aCollection"
       
   111 
       
   112     |index1 "{ Class: SmallInteger }"
       
   113      index2 "{ Class: SmallInteger }" 
       
   114      stop   "{ Class: SmallInteger }" |
       
   115 
       
   116     (aCollection == self) ifTrue:[^true].
       
   117     (aCollection isKindOf:SequenceableCollection) ifFalse:[^false].
       
   118 
       
   119     stop := aCollection size.
       
   120     stop > self size ifTrue:[^false].
       
   121 
       
   122     index1 := self size.
       
   123     index2 := aCollection size.
       
   124     [index2 > 0] whileTrue:[
       
   125         (self at:index1) = (aCollection at:index2) ifFalse:[^false].
       
   126         index1 := index1 - 1.
       
   127         index2 := index2 - 1
       
   128     ].
       
   129     ^ true
       
   130 
       
   131     "'abcde' endsWith:#($d $e)"
       
   132     "#[1 2 3 4] endsWith:#(3 4)"
       
   133     "#(1 2 3 4) asOrderedCollection endsWith:#(3 4)"
       
   134 ! !
       
   135 
       
   136 !SequenceableCollection methodsFor:'testing'!
       
   137 
       
   138 size
       
   139     "return the number of elements in the collection.
       
   140      concrete implementations must define this"
       
   141 
       
   142     ^ self subclassResponsibility
       
   143 ! !
       
   144 
       
   145 !SequenceableCollection methodsFor:'copying'!
       
   146 
       
   147 , aCollection
       
   148     "return a new collection formed from concatenating the receiver with
       
   149      the argument"
       
   150 
       
   151     |newCollection 
       
   152      mySize    "{ Class: SmallInteger }"
       
   153      newSize   "{ Class: SmallInteger }"
       
   154      otherSize "{ Class: SmallInteger }"
       
   155      dstIndex  "{ Class: SmallInteger }"|
       
   156 
       
   157     mySize := self size.
       
   158     otherSize := aCollection size.
       
   159     newSize := mySize + otherSize.
       
   160     newCollection := self species new:newSize.
       
   161 
       
   162     newCollection replaceFrom:1 to:mySize with:self startingAt:1.
       
   163     dstIndex := mySize + 1.
       
   164     (aCollection isKindOf:SequenceableCollection) ifTrue:[
       
   165         "yes, aCollection has indexed elements"
       
   166         newCollection replaceFrom:dstIndex to:newSize
       
   167                              with:aCollection startingAt:1.
       
   168         ^ newCollection
       
   169     ] ifFalse:[
       
   170         "no, enumerate aCollection"
       
   171         aCollection do:[:element |
       
   172             newCollection at:dstIndex put:element.
       
   173             dstIndex := dstIndex + 1
       
   174         ]
       
   175     ].
       
   176     ^ newCollection
       
   177 !
       
   178 
       
   179 copyWith:newElement
       
   180     "return a new collection consisting of receivers elements
       
   181      plus the argument"
       
   182 
       
   183     |newCollection mySize newSize|
       
   184 
       
   185     mySize := self size.
       
   186     newSize := mySize + 1.
       
   187     newCollection := self species new:newSize.
       
   188     newCollection replaceFrom:1 to:mySize with:self startingAt:1.
       
   189     newCollection at:newSize put:newElement.
       
   190     ^newCollection
       
   191 !
       
   192 
       
   193 copyWithout:anElement
       
   194     "return a new collection consisting of receivers elements
       
   195      without anElement (if it was present)"
       
   196 
       
   197     |newCollection skipIndex 
       
   198      dstIndex "{ Class: SmallInteger }"
       
   199      index    "{ Class: SmallInteger }"
       
   200      stop     "{ Class: SmallInteger }" |
       
   201 
       
   202     skipIndex := self indexOf:anElement startingAt:1.
       
   203     (skipIndex == 0) ifTrue:[^ self copy].
       
   204     stop := self size.
       
   205     newCollection := self class new:(stop - 1).
       
   206     dstIndex := 1.
       
   207     index := 1.
       
   208     [index <= stop] whileTrue:[
       
   209         (index ~~ skipIndex) ifTrue:[
       
   210             newCollection at:dstIndex put:(self at:index).
       
   211             dstIndex := dstIndex + 1
       
   212         ].
       
   213         index := index + 1
       
   214     ].
       
   215     ^ newCollection
       
   216 !
       
   217 
       
   218 copyFrom:start to:stop
       
   219     "return a new collection consisting of receivers elements
       
   220      between start and stop"
       
   221 
       
   222     |newCollection newSize|
       
   223 
       
   224     newSize := stop - start + 1.
       
   225     newCollection := self class new:newSize.
       
   226     newCollection replaceFrom:1 to:newSize with:self startingAt:start.
       
   227     ^ newCollection
       
   228 !
       
   229 
       
   230 copyFrom:start
       
   231     "return a new collection consisting of receivers elements
       
   232      from start to the end of the collection"
       
   233 
       
   234     ^ self copyFrom:start to:(self size)
       
   235 !
       
   236 
       
   237 copyTo:stop
       
   238     "return a new collection consisting of receivers elements
       
   239      from 1 up to index stop"
       
   240 
       
   241     ^ self copyFrom:1 to:stop
       
   242 !
       
   243 
       
   244 copyWithoutIndex:omitIndex
       
   245     "return a new collection consisting of receivers elements
       
   246      without the argument stored at omitIndex"
       
   247 
       
   248     |copy|
       
   249 
       
   250     copy := self class new:(self size - 1).
       
   251     copy replaceFrom:1 to:(omitIndex - 1) with:self startingAt:1.
       
   252     copy replaceFrom:omitIndex to:(copy size) 
       
   253                 with:self startingAt:(omitIndex + 1).
       
   254     ^ copy
       
   255 ! !
       
   256 
       
   257 !SequenceableCollection methodsFor:'filling and replacing'!
       
   258 
       
   259 from:index1 to:index2 put:anObject
       
   260     "replace the elements from index1 to index2 of the collection
       
   261      by the argument, anObject"
       
   262 
       
   263     |index "{ Class: SmallInteger }"
       
   264      end   "{ Class: SmallInteger }"|
       
   265 
       
   266     index := index1.
       
   267     end := index2.
       
   268     [index <= end] whileTrue:[
       
   269         self at:index put:anObject.
       
   270         index := index + 1
       
   271     ]
       
   272 !
       
   273 
       
   274 atAllPut:anObject
       
   275     "replace all elements of the collection by the argument, anObject"
       
   276 
       
   277     self from:1 to:(self size) put:anObject
       
   278 !
       
   279 
       
   280 atAll:indexCollection put:anObject
       
   281     "put anObject into all indexes from indexCollection in the receiver"
       
   282 
       
   283     indexCollection do:[:index | self at:index put:anObject]
       
   284 
       
   285     "(Array new:10) atAll:(1 to:5) put:0"
       
   286     "(Array new:10) atAll:#(1 5 6 9) put:0"
       
   287 !
       
   288 
       
   289 replaceAll:oldObject by:newObject
       
   290     "replace all oldObjects by newObject in the receiver"
       
   291 
       
   292     1 to:self size do:[:index |
       
   293         (self at:index) = oldObject ifTrue:[
       
   294             self at:index put:newObject
       
   295         ]
       
   296     ]
       
   297 !
       
   298 
       
   299 replaceFrom:start with:replacementCollection
       
   300     "replace elements starting at start with elements
       
   301      taken from replacementCollection (starting at 1)"
       
   302 
       
   303     ^ self replaceFrom:start 
       
   304                     to:(start + replacementCollection size - 1)
       
   305                   with:replacementCollection
       
   306             startingAt:1
       
   307 !
       
   308 
       
   309 replaceFrom:start to:stop with:replacementCollection
       
   310     "replace elements between index start and stop with elements
       
   311      taken from replacementCollection (starting at 1)"
       
   312 
       
   313     ^ self replaceFrom:start
       
   314                     to:stop
       
   315                   with:replacementCollection
       
   316             startingAt:1
       
   317 !
       
   318 
       
   319 replaceFrom:start to:stop with:replacementCollection startingAt:repStart
       
   320     "replace elements between index start and stop with elements
       
   321      taken from replacementCollection (starting at repStart)"
       
   322 
       
   323     |srcIndex "{ Class: SmallInteger }"
       
   324      dstIndex "{ Class: SmallInteger }"
       
   325      end      "{ Class: SmallInteger }" |
       
   326 
       
   327     (replacementCollection == self) ifTrue:[
       
   328         (repStart < start) ifTrue:[
       
   329             " must do reverse copy "
       
   330             srcIndex := repStart + (stop - start).
       
   331             dstIndex := stop.
       
   332             end := start.
       
   333             [dstIndex >= end] whileTrue:[
       
   334                 self at:dstIndex put:(replacementCollection at:srcIndex).
       
   335                 srcIndex := srcIndex - 1.
       
   336                 dstIndex := dstIndex - 1
       
   337             ].
       
   338             ^ self
       
   339         ]
       
   340     ].
       
   341 
       
   342     srcIndex := repStart.
       
   343     dstIndex := start.
       
   344     end := stop.
       
   345     [dstIndex <= end] whileTrue:[
       
   346         self at:dstIndex put:(replacementCollection at:srcIndex).
       
   347         srcIndex := srcIndex + 1.
       
   348         dstIndex := dstIndex + 1
       
   349     ]
       
   350 !
       
   351 
       
   352 withCRs
       
   353     "return a new collection consisting of receivers elements
       
   354      with all \-characters replaced by cr-characters"
       
   355 
       
   356     |newCollection
       
   357      size "{ Class: SmallInteger }" |
       
   358 
       
   359     newCollection := self copy.
       
   360     size := self size.
       
   361     1 to:size do:[:index |
       
   362         ((self at:index) == $\) ifTrue:[
       
   363             newCollection at:index put:(Character cr)
       
   364         ]
       
   365     ].
       
   366     ^ newCollection
       
   367 !
       
   368 
       
   369 withoutCRs
       
   370     "return a new collection consisting of receivers elements
       
   371      with all cr-characters replaced by \-characters"
       
   372 
       
   373     |newCollection 
       
   374      size "{ Class: SmallInteger }" |
       
   375 
       
   376     newCollection := self copy.
       
   377     size := self size.
       
   378     1 to:size do:[:index|
       
   379         ((self at:index) == Character cr) ifTrue:[
       
   380             newCollection at:index put:$\
       
   381         ]
       
   382     ].
       
   383     ^ newCollection
       
   384 ! !
       
   385 
       
   386 !SequenceableCollection methodsFor:'adding & removing'!
       
   387 
       
   388 addFirst:anElement
       
   389     "prepend the argument, anElement to the collection"
       
   390 
       
   391     |newSize|
       
   392 
       
   393     newSize := self size + 1.
       
   394     self grow:newSize.
       
   395     self replaceFrom:2 to:newSize with:self startingAt:1.
       
   396     self at:1 put:anElement
       
   397 !
       
   398 
       
   399 add:anElement
       
   400     "append the argument, anElement to the collection"
       
   401 
       
   402     |newSize|
       
   403 
       
   404     newSize := self size + 1.
       
   405     self grow:newSize.
       
   406     self at:newSize put:anElement
       
   407 !
       
   408 
       
   409 add:anElement beforeIndex:index
       
   410     "insert the first argument, anObject into the collection before slot index"
       
   411 
       
   412     |newSize|
       
   413 
       
   414     newSize := self size + 1.
       
   415     self grow:newSize.
       
   416     self replaceFrom:index + 1 to:newSize with:self startingAt:index.
       
   417     self at:index put:anElement
       
   418 !
       
   419 
       
   420 remove:anElement ifAbsent:aBlock
       
   421     "search for anElement and, if present remove it; if not present
       
   422      return the value of evaluating aBlock"
       
   423 
       
   424     |any 
       
   425      dstIndex "{ Class: SmallInteger }"
       
   426      sz       "{ Class: SmallInteger }"|
       
   427 
       
   428     dstIndex := 1.
       
   429     any := false.
       
   430     sz := self size.
       
   431     1 to:sz do:[:srcIndex |
       
   432         (anElement = (self at:srcIndex)) ifTrue:[
       
   433             any := true
       
   434         ] ifFalse:[
       
   435             (dstIndex ~~ srcIndex) ifTrue:[
       
   436                 self at:dstIndex put:(self at:srcIndex)
       
   437             ].
       
   438             dstIndex := dstIndex + 1
       
   439         ]
       
   440     ].
       
   441     any ifTrue:[
       
   442         self grow:dstIndex - 1
       
   443     ] ifFalse:[
       
   444         aBlock value
       
   445     ]
       
   446 !
       
   447 
       
   448 removeFromIndex:startIndex toIndex:endIndex
       
   449     "remove the elements stored at indexes between startIndex and endIndex"
       
   450 
       
   451     |newSize|
       
   452 
       
   453     newSize := self size - endIndex + startIndex - 1.
       
   454     self replaceFrom:startIndex to:newSize with:self startingAt:(endIndex + 1).
       
   455     self grow:newSize
       
   456 !
       
   457 
       
   458 removeIndex:index
       
   459     "remove the argument stored at index"
       
   460 
       
   461     self removeFromIndex:index toIndex:index
       
   462 ! !
       
   463 
       
   464 !SequenceableCollection methodsFor:'searching'!
       
   465 
       
   466 detect:aBlock ifNone:exceptionBlock
       
   467     "find the first element, for which evaluation of the argument, aBlock
       
   468      return true; if none does so, return the evaluation of exceptionBlock
       
   469 
       
   470     reimplemented here for speed"
       
   471 
       
   472     |index "{ Class: SmallInteger }"
       
   473      stop  "{ Class: SmallInteger }"
       
   474      element|
       
   475 
       
   476     stop := self size.
       
   477     index := 1.
       
   478     [index <= stop] whileTrue:[
       
   479         element := self at:index.
       
   480         (aBlock value:element) ifTrue:[
       
   481             ^ element
       
   482         ].
       
   483         index := index + 1
       
   484     ].
       
   485     ^ exceptionBlock value
       
   486 !
       
   487 
       
   488 indexOf:anElement
       
   489     "search the collection for anElement;
       
   490      if found, return the index otherwise return 0.
       
   491      The comparison is done using = (i.e. equality test)."
       
   492 
       
   493     ^ self indexOf:anElement startingAt:1
       
   494 !
       
   495 
       
   496 indexOf:anElement ifAbsent:exceptionBlock
       
   497     "search the collection for anElement;
       
   498      if found, return the index otherwise return the value of the
       
   499      exceptionBlock.
       
   500      The comparison is done using = (i.e. equality test)."
       
   501 
       
   502     |index|
       
   503 
       
   504     index := self indexOf:anElement startingAt:1.
       
   505     (index == 0) ifTrue:[^ exceptionBlock value].
       
   506     ^ index
       
   507 !
       
   508 
       
   509 indexOf:anElement startingAt:start
       
   510     "search the collection for anElement staring search at index start;
       
   511      if found, return the index otherwise return 0.
       
   512      The comparison is done using = (i.e. equality test)."
       
   513 
       
   514     |index "{ Class: SmallInteger }"
       
   515      stop  "{ Class: SmallInteger }" |
       
   516 
       
   517     index := start.
       
   518     stop := self size.
       
   519     [index <= stop] whileTrue:[
       
   520         anElement = (self at:index) ifTrue:[^ index].
       
   521         index := index + 1
       
   522     ].
       
   523     ^ 0
       
   524 !
       
   525 
       
   526 indexOf:anElement startingAt:start ifAbsent:exceptionBlock
       
   527     "search the collection for anElement starting search at start;
       
   528      if found, return the index otherwise return the value of the
       
   529      exceptionBlock.
       
   530      The comparison is done using = (i.e. equality test)."
       
   531 
       
   532     |index|
       
   533 
       
   534     index := self indexOf:anElement startingAt:start.
       
   535     (index == 0) ifTrue:[^ exceptionBlock value].
       
   536     ^ index
       
   537 !
       
   538 
       
   539 identityIndexOf:anElement
       
   540     "search the collection for anElement using identity compare (i.e. ==);
       
   541      if found, return the index otherwise return 0."
       
   542 
       
   543     ^ self identityIndexOf:anElement startingAt:1
       
   544 !
       
   545 
       
   546 identityIndexOf:anElement ifAbsent:exceptionBlock
       
   547     "search the collection for anElement using identity compare (i.e. ==);
       
   548      if found, return the index otherwise return the value of the
       
   549      exceptionBlock."
       
   550 
       
   551     |index|
       
   552 
       
   553     index := self identityIndexOf:anElement startingAt:1.
       
   554     (index == 0) ifTrue:[^ exceptionBlock value].
       
   555     ^ index
       
   556 !
       
   557 
       
   558 identityIndexOf:anElement startingAt:start
       
   559     "search the collection for anElement staring search at index start
       
   560      using identity compare  (i.e. ==);
       
   561      if found, return the index otherwise return 0."
       
   562 
       
   563     |index "{ Class: SmallInteger }"
       
   564      stop  "{ Class: SmallInteger }" |
       
   565 
       
   566     index := start.
       
   567     stop := self size.
       
   568     [index <= stop] whileTrue:[
       
   569         anElement == (self at:index) ifTrue:[^ index].
       
   570         index := index + 1
       
   571     ].
       
   572     ^ 0
       
   573 !
       
   574 
       
   575 identityIndexOf:anElement startingAt:start ifAbsent:exceptionBlock
       
   576     "search the collection for anElement starting search at start;
       
   577      if found, return the index otherwise return the value of the
       
   578      exceptionBlock.
       
   579      This one searches for identical objects (i.e. ==)."
       
   580 
       
   581     |index|
       
   582 
       
   583     index := self identityIndexOf:anElement startingAt:start.
       
   584     (index == 0) ifTrue:[^ exceptionBlock value].
       
   585     ^ index
       
   586 !
       
   587 
       
   588 findFirst:aBlock
       
   589     "find the first element, for which evaluation of the argument, aBlock
       
   590      return true; return its index or 0 if none detected."
       
   591 
       
   592     |index "{ Class: SmallInteger }"
       
   593      stop  "{ Class: SmallInteger }" |
       
   594 
       
   595     stop := self size.
       
   596     index := 1.
       
   597     [index <= stop] whileTrue:[
       
   598         (aBlock value:(self at:index)) ifTrue:[^ index].
       
   599         index := index + 1
       
   600     ].
       
   601     ^ 0
       
   602 
       
   603     "#(1 2 3 4 5 6) findFirst:[:x | (x > 3) and:[x even]]"
       
   604 !
       
   605 
       
   606 includes:anElement
       
   607     "return true if the collection contains anElement; false otherwise.
       
   608      Comparison is done using equality compare (i.e. =)."
       
   609 
       
   610     ((self indexOf:anElement startingAt:1) == 0) ifTrue:[^ false].
       
   611     ^ true
       
   612 ! !
       
   613 
       
   614 !SequenceableCollection methodsFor:'sorting & reordering'!
       
   615 
       
   616 reverse
       
   617     "reverse the order of the arguments inplace"
       
   618 
       
   619     |lowIndex "{ Class: SmallInteger }"
       
   620      hiIndex  "{ Class: SmallInteger }"
       
   621      t|
       
   622 
       
   623     hiIndex := self size.
       
   624     lowIndex := 1.
       
   625     [lowIndex < hiIndex] whileTrue:[
       
   626         t := self at:lowIndex.
       
   627         self at:lowIndex put:(self at:hiIndex). 
       
   628         self at:hiIndex put:t.
       
   629         lowIndex := lowIndex + 1.
       
   630         hiIndex := hiIndex - 1
       
   631     ]
       
   632     "#(4 5 6 7 7) reverse"
       
   633 !
       
   634 
       
   635 quickSortFrom:begin to:end
       
   636     "actual quicksort worker for sort-message"
       
   637 
       
   638     |b "{ Class: SmallInteger }"
       
   639      e "{ Class: SmallInteger }"
       
   640      middleElement temp |
       
   641 
       
   642     b := begin.
       
   643     e := end.
       
   644     middleElement := self at:((b + e) // 2).
       
   645 
       
   646     [b < e] whileTrue:[
       
   647         [b < end and:[(self at:b) < middleElement]] whileTrue:[b := b + 1].
       
   648         [e > begin and:[middleElement < (self at:e)]] whileTrue:[e := e - 1].
       
   649 
       
   650         (b <= e) ifTrue:[
       
   651             (b == e) ifFalse:[
       
   652                 temp := self at:b.
       
   653                 self at:b put:(self at:e).
       
   654                 self at:e put:temp
       
   655             ].
       
   656             b := b + 1.
       
   657             e := e - 1
       
   658         ]
       
   659     ].
       
   660     (begin < e) ifTrue:[self quickSortFrom:begin to:e].
       
   661     (b < end) ifTrue:[self quickSortFrom:b to:end]
       
   662 !
       
   663 
       
   664 quickSortFrom:begin to:end with:aCollection
       
   665     "actual quicksort worker for sortWith-message"
       
   666 
       
   667     |b "{ Class: SmallInteger }"
       
   668      e "{ Class: SmallInteger }"
       
   669      middleElement temp |
       
   670 
       
   671     b := begin.
       
   672     e := end.
       
   673     middleElement := self at:((b + e) // 2).
       
   674 
       
   675     [b < e] whileTrue:[
       
   676         [b < end and:[(self at:b) < middleElement]] whileTrue:[b := b + 1].
       
   677         [e > begin and:[middleElement < (self at:e)]] whileTrue:[e := e - 1].
       
   678 
       
   679         (b <= e) ifTrue:[
       
   680             (b == e) ifFalse:[
       
   681                 temp := self at:b.
       
   682                 self at:b put:(self at:e).
       
   683                 self at:e put:temp.
       
   684                 temp := aCollection at:b.
       
   685                 aCollection at:b put:(aCollection at:e).
       
   686                 aCollection at:e put:temp
       
   687             ].
       
   688             b := b + 1.
       
   689             e := e - 1
       
   690         ]
       
   691     ].
       
   692     (begin < e) ifTrue:[self quickSortFrom:begin to:e with:aCollection].
       
   693     (b < end) ifTrue:[self quickSortFrom:b to:end with:aCollection]
       
   694 !
       
   695 
       
   696 quickSortFrom:begin to:end sortBlock:sortBlock
       
   697     "actual quicksort worker for sort:-message"
       
   698 
       
   699     |b "{ Class: SmallInteger }"
       
   700      e "{ Class: SmallInteger }"
       
   701      middleElement temp |
       
   702 
       
   703     b := begin.
       
   704     e := end.
       
   705     middleElement := self at:((b + e) // 2).
       
   706 
       
   707     [b < e] whileTrue:[
       
   708         [b < end and:[sortBlock value:(self at:b) value:middleElement]] whileTrue:[b := b + 1].
       
   709         [e > begin and:[sortBlock value:middleElement value:(self at:e)]] whileTrue:[e := e - 1].
       
   710 
       
   711         (b <= e) ifTrue:[
       
   712             (b == e) ifFalse:[
       
   713                 temp := self at:b.
       
   714                 self at:b put:(self at:e).
       
   715                 self at:e put:temp
       
   716             ].
       
   717             b := b + 1.
       
   718             e := e - 1
       
   719         ]
       
   720     ].
       
   721     (begin < e) ifTrue:[self quickSortFrom:begin to:e sortBlock:sortBlock].
       
   722     (b < end) ifTrue:[self quickSortFrom:b to:end sortBlock:sortBlock]
       
   723 !
       
   724 
       
   725 quickSortFrom:begin to:end sortBlock:sortBlock with:aCollection
       
   726     "actual quicksort worker for sort:with:-message"
       
   727 
       
   728     |b "{ Class: SmallInteger }"
       
   729      e "{ Class: SmallInteger }"
       
   730      middleElement temp |
       
   731 
       
   732     b := begin.
       
   733     e := end.
       
   734     middleElement := self at:((b + e) // 2).
       
   735 
       
   736     [b < e] whileTrue:[
       
   737         [b < end and:[sortBlock value:(self at:b) value:middleElement]] whileTrue:[b := b + 1].
       
   738         [e > begin and:[sortBlock value:middleElement value:(self at:e)]] whileTrue:[e := e - 1].
       
   739 
       
   740         (b <= e) ifTrue:[
       
   741             (b == e) ifFalse:[
       
   742                 temp := self at:b.
       
   743                 self at:b put:(self at:e).
       
   744                 self at:e put:temp.
       
   745                 temp := aCollection at:b.
       
   746                 aCollection at:b put:(aCollection at:e).
       
   747                 aCollection at:e put:temp
       
   748             ].
       
   749             b := b + 1.
       
   750             e := e - 1
       
   751         ]
       
   752     ].
       
   753     (begin < e) ifTrue:[self quickSortFrom:begin to:e sortBlock:sortBlock with:aCollection].
       
   754     (b < end) ifTrue:[self quickSortFrom:b to:end sortBlock:sortBlock with:aCollection]
       
   755 !
       
   756 
       
   757 bubbleSort
       
   758     "sort the collection inplace using bubbleSort (sloooow)
       
   759      - this one makes only sense to sort after inserting an element into
       
   760        an already sorted collection (if at all)"
       
   761 
       
   762     |index  "{ Class: SmallInteger }"
       
   763      index2 "{ Class: SmallInteger }"
       
   764      end    "{ Class: SmallInteger }"
       
   765      smallest smallestIndex thisOne|
       
   766 
       
   767     end := self size.
       
   768     index := 1.
       
   769     [index <= end] whileTrue:[
       
   770         smallest := self at:index.
       
   771         smallestIndex := index.
       
   772         index2 := index + 1.
       
   773         [index2 <= end] whileTrue:[
       
   774             (self at:index2) < smallest ifTrue:[
       
   775                 smallestIndex := index2.
       
   776                 smallest := self at:index2
       
   777             ].
       
   778             index2 := index2 + 1
       
   779         ].
       
   780         (smallestIndex ~~ index) ifTrue:[
       
   781             thisOne := self at:index.
       
   782             self at:index put:smallest.
       
   783             self at:smallestIndex put:thisOne
       
   784         ].
       
   785         index := index + 1
       
   786     ]
       
   787 
       
   788     "#(1 16 7 98 3 19 4 0) bubbleSort"
       
   789 !
       
   790 
       
   791 sort
       
   792     "sort the collection inplace. The elements are compared using
       
   793      > and < i.e. they should offer a magnitude-like protocol."
       
   794     |sz|
       
   795 
       
   796     sz := self size.
       
   797     (sz > 1) ifTrue:[
       
   798         self quickSortFrom:1 to:sz
       
   799     ]
       
   800 
       
   801     "#(1 16 7 98 3 19 4 0) sort"
       
   802 !
       
   803 
       
   804 sortWith:aCollection
       
   805     "sort the receiver collection inplace, also sort aCollection with it.
       
   806      Use, when you have a key collection to sort another collection with."
       
   807 
       
   808     |sz|
       
   809 
       
   810     sz := self size.
       
   811     (sz > 1) ifTrue:[
       
   812         self quickSortFrom:1 to:sz with:aCollection
       
   813     ]
       
   814 
       
   815     "|c1 c2|
       
   816      c1 := #(1 16 7 9).
       
   817      c2 := #('one' 'sixteen' 'seven' 'nine').
       
   818      c1 sortWith:c2.
       
   819      c1 printNewline.
       
   820      c2 printNewline"
       
   821 !
       
   822 
       
   823 sort:sortBlock
       
   824     "sort the collection inplace using the 2-arg block sortBlock
       
   825      for comparison. This allows any sort criteria to be implemented."
       
   826 
       
   827     |sz|
       
   828 
       
   829     sz := self size.
       
   830     (sz > 1) ifTrue:[
       
   831         self quickSortFrom:1 to:sz sortBlock:sortBlock
       
   832     ]
       
   833 
       
   834     "#(1 16 7 98 3 19 4 0) sort:[:a :b | a < b]"
       
   835     "#(1 16 7 98 3 19 4 0) sort:[:a :b | a > b]"
       
   836 !
       
   837 
       
   838 sort:sortBlock with:aCollection
       
   839     "sort the collection inplace using the 2-arg block sortBlock
       
   840      for comparison. Also reorder the elements in aCollection"
       
   841 
       
   842     |sz|
       
   843 
       
   844     sz := self size.
       
   845     (sz > 1) ifTrue:[
       
   846         self quickSortFrom:1 to:sz sortBlock:sortBlock with:aCollection
       
   847     ]
       
   848 
       
   849     "|c1 c2|
       
   850      c1 := #(1 16 7 9).
       
   851      c2 := #('one' 'sixteen' 'seven' 'nine').
       
   852      c1 sort:[:a :b | a > b] with:c2.
       
   853      c1 printNewline.
       
   854      c2 printNewline"
       
   855 ! !
       
   856 
       
   857 !SequenceableCollection methodsFor:'enumerating'!
       
   858 
       
   859 do:aBlock
       
   860     "evaluate the argument, aBlock for every element in the collection."
       
   861 
       
   862     |index  "{ Class:SmallInteger }"
       
   863      length "{ Class:SmallInteger }"|
       
   864 
       
   865     index := 1.
       
   866     length := self size.
       
   867     [index <= length] whileTrue:[
       
   868         aBlock value:(self at:index).
       
   869         index := index + 1
       
   870     ]
       
   871 !
       
   872 
       
   873 from:index1 to:index2 do:aBlock
       
   874     "evaluate the argument, aBlock for the elements with index index1 to
       
   875      index2 in the collection"
       
   876 
       
   877     |index "{ Class:SmallInteger }"
       
   878      stop  "{ Class:SmallInteger }" |
       
   879 
       
   880     index := index1.
       
   881     stop := index2.
       
   882     [index <= stop] whileTrue:[
       
   883         aBlock value:(self at:index).
       
   884         index := index + 1
       
   885     ]
       
   886 !
       
   887 
       
   888 with:aCollection do:aBlock
       
   889     "evaluate the argument, aBlock for successive elements from
       
   890      each of the two collections self and aCollection.
       
   891      aBlock must be a two-argument block"
       
   892 
       
   893     |index "{ Class: SmallInteger }"
       
   894      stop  "{ Class: SmallInteger }" |
       
   895 
       
   896     index := 1.
       
   897     stop := self size.
       
   898     [index <= stop] whileTrue:[
       
   899         aBlock value:(self at:index) value:(aCollection at:index).
       
   900         index := index + 1
       
   901     ]
       
   902 !
       
   903 
       
   904 reverseDo:aBlock
       
   905     "evaluate the argument, aBlock for every element in the collection
       
   906      in reverse order"
       
   907 
       
   908     |index "{ Class:SmallInteger }" |
       
   909 
       
   910     index := self size.
       
   911     [index > 0] whileTrue:[
       
   912         aBlock value:(self at:index).
       
   913         index := index - 1
       
   914     ]
       
   915 !
       
   916 
       
   917 collect:aBlock
       
   918     "evaluate the argument, aBlock for every element in the collection
       
   919      and return a collection of the results"
       
   920 
       
   921     |newCollection
       
   922      index  "{ Class:SmallInteger }"
       
   923      length "{ Class:SmallInteger }" |
       
   924 
       
   925     length := self size.
       
   926     newCollection := self species new:length.
       
   927     index := 1.
       
   928     [index <= length] whileTrue:[
       
   929         newCollection at:index put:(aBlock value:(self at:index)).
       
   930         index := index + 1
       
   931     ].
       
   932     ^ newCollection
       
   933 !
       
   934 
       
   935 select:aBlock
       
   936     "evaluate the argument, aBlock for every element in the collection
       
   937      and return a collection of all elements for which the block return
       
   938      true"
       
   939 
       
   940     |element newColl
       
   941      index  "{ Class:SmallInteger }"
       
   942      length "{ Class:SmallInteger }" |
       
   943 
       
   944     length := self size.
       
   945     newColl := OrderedCollection new:length.
       
   946     index := 1.
       
   947     [index <= length] whileTrue:[
       
   948         element := self at:index.
       
   949         (aBlock value:element) ifTrue:[
       
   950             newColl add:element
       
   951         ].
       
   952         index := index + 1
       
   953     ].
       
   954     ^ newColl
       
   955 ! !