OrderedCollection.st
changeset 2362 23574f29c8af
parent 2361 dd95b53674e9
child 2364 788423a8d67f
equal deleted inserted replaced
2361:dd95b53674e9 2362:23574f29c8af
   507 
   507 
   508 remove:anObject ifAbsent:exceptionBlock
   508 remove:anObject ifAbsent:exceptionBlock
   509     "remove the first element which is equal to anObject;
   509     "remove the first element which is equal to anObject;
   510      if found, remove and return it; 
   510      if found, remove and return it; 
   511      if not, return the value from evaluating exceptionBlock.
   511      if not, return the value from evaluating exceptionBlock.
   512      Used equality compare (=) to search for the element."
   512      Uses equality compare (=) to search for the element."
   513 
   513 
   514     |index retVal|
   514     |index retVal|
   515 
   515 
   516     index := contentsArray indexOf:anObject startingAt:firstIndex endingAt:lastIndex.
   516     index := contentsArray indexOf:anObject startingAt:firstIndex endingAt:lastIndex.
   517     index ~~ 0 ifTrue:[
   517     index ~~ 0 ifTrue:[
   530      #(1 2 3 4 5) asOrderedCollection remove:9 ifAbsent:'oops' 
   530      #(1 2 3 4 5) asOrderedCollection remove:9 ifAbsent:'oops' 
   531      #(1.0 2.0 3.0 4.0 5.0) asOrderedCollection remove:4 ifAbsent:'oops' 
   531      #(1.0 2.0 3.0 4.0 5.0) asOrderedCollection remove:4 ifAbsent:'oops' 
   532      #(1.0 2.0 3.0 4.0 5.0) asOrderedCollection removeIdentical:4 ifAbsent:'oops' 
   532      #(1.0 2.0 3.0 4.0 5.0) asOrderedCollection removeIdentical:4 ifAbsent:'oops' 
   533     "
   533     "
   534 
   534 
   535     "Modified: 8.2.1997 / 18:59:22 / cg"
   535     "Modified: 8.2.1997 / 19:17:19 / cg"
   536 !
   536 !
   537 
   537 
   538 removeAll
   538 removeAll
   539     "remove all elements from the collection.
   539     "remove all elements from the collection.
   540      Returns the receiver."
   540      Returns the receiver."
   549      The argument, aBlock is evaluated for successive elements and all those,
   549      The argument, aBlock is evaluated for successive elements and all those,
   550      for which it returns true, are removed.
   550      for which it returns true, are removed.
   551      Return a collection containing the removed elements.
   551      Return a collection containing the removed elements.
   552 
   552 
   553      Performance hint:
   553      Performance hint:
   554 	if a big number of objects is removed this way,
   554         if a large number of objects is to be removed this way,
   555         it may be better to rebuild a new collection via #select:,
   555         it may be better to rebuild a new collection via #select:,
   556         since removing elements out of the middle is somewhat slow
   556         since removing elements out of the middle is somewhat slow
   557 	due to the need to copy over remaining elements within the collection."
   557         due to the need to copy over remaining elements within the collection."
   558 
   558 
   559     "/ this is a q&d implementation (possibly slow).
   559     "/ this is a q&d implementation (possibly slow).
   560 
   560 
   561     |runIndex removed element|
   561     |runIndex removed element sz|
   562 
   562 
   563     removed := self species new.
   563     removed := self species new.
   564 
   564 
   565     runIndex := 1.
   565     runIndex := 1.
   566     [runIndex <= self size] whileTrue:[
   566     sz := self size.
       
   567     [runIndex <= sz] whileTrue:[
   567         element := self at:runIndex.
   568         element := self at:runIndex.
   568         (aBlock value:element) ifTrue:[
   569         (aBlock value:element) ifTrue:[
   569             removed add:element.
   570             removed add:element.
   570             self removeAtIndex:runIndex
   571             self removeAtIndex:runIndex.
       
   572             sz := sz - 1.
   571         ] ifFalse:[
   573         ] ifFalse:[
   572             runIndex := runIndex + 1
   574             runIndex := runIndex + 1
   573         ]
   575         ]
   574     ].
   576     ].
   575     ^ removed
   577     ^ removed
   580      coll := OrderedCollection withAll:(1 to:10).
   582      coll := OrderedCollection withAll:(1 to:10).
   581      Transcript showCR:(coll removeAllSuchThat:[:el | el even]).
   583      Transcript showCR:(coll removeAllSuchThat:[:el | el even]).
   582      Transcript showCR:coll
   584      Transcript showCR:coll
   583     "
   585     "
   584 
   586 
   585     "Modified: 12.4.1996 / 13:37:01 / cg"
   587     "Modified: 8.2.1997 / 19:19:00 / cg"
   586 !
   588 !
   587 
   589 
   588 removeFirst
   590 removeFirst
   589     "remove the first element from the collection; return the element."
   591     "remove the first element from the collection; return the element."
   590 
   592 
   591     |anObject |
   593     |anObject fI "{ Class: SmallInteger }" |
   592 
   594 
   593     firstIndex > lastIndex ifTrue:[
   595     fI := firstIndex.
       
   596 
       
   597     fI > lastIndex ifTrue:[
   594         "error if collection is empty"
   598         "error if collection is empty"
   595         ^ self emptyCollectionError.
   599         ^ self emptyCollectionError.
   596     ].
   600     ].
   597 
   601 
   598     anObject := contentsArray at:firstIndex.
   602     anObject := contentsArray at:fI.
   599 
   603 
   600     "/ nil it out, to allow GC to reclaim it.
   604     "/ nil it out, to allow GC to reclaim it.
   601     contentsArray at:firstIndex put:nil.
   605     contentsArray at:fI put:nil.
   602 
   606 
   603     firstIndex := firstIndex + 1.
   607     fI := fI + 1.
   604 
   608 
   605     firstIndex > lastIndex ifTrue:[
   609     fI > lastIndex ifTrue:[
   606         "reset to avoid ever growing"
   610         "reset to avoid ever growing"
   607         firstIndex := 1.
   611         fI := 1.
   608         lastIndex := 0 
   612         lastIndex := 0 
   609     ].
   613     ].
       
   614     firstIndex := fI.
   610     ^ anObject
   615     ^ anObject
   611 
   616 
   612     "
   617     "
   613      (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst; yourself
   618      (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst; yourself
   614      OrderedCollection new removeFirst
   619      OrderedCollection new removeFirst
   615      (SortedCollection withAll:#(5 4 3 2 1)) removeFirst; yourself
   620      (SortedCollection withAll:#(5 4 3 2 1)) removeFirst; yourself
   616     "
   621     "
   617 
   622 
   618     "Modified: 1.2.1997 / 12:30:50 / cg"
   623     "Modified: 8.2.1997 / 19:14:39 / cg"
   619 !
   624 !
   620 
   625 
   621 removeFirst:n
   626 removeFirst:n
   622     "remove the first n elements from the collection; 
   627     "remove the first n elements from the collection; 
   623      Return a collection containing the removed elements."
   628      Return a collection containing the removed elements."
   624 
   629 
   625     |mySize ret|
   630     |mySize ret newFirstIndex|
   626 
   631 
   627     mySize := self size.
   632     mySize := self size.
   628     mySize < n ifTrue:[
   633     mySize < n ifTrue:[
   629         "error if collection has not enough elements"
   634         "error if collection has not enough elements"
   630         ^ self notEnoughElementsError.
   635         ^ self notEnoughElementsError.
   634     ret replaceFrom:1 to:n with:contentsArray startingAt:firstIndex.
   639     ret replaceFrom:1 to:n with:contentsArray startingAt:firstIndex.
   635 
   640 
   636     "/
   641     "/
   637     "/ nil-out contents array, to not keep elements from being GC'd
   642     "/ nil-out contents array, to not keep elements from being GC'd
   638     "/
   643     "/
   639     contentsArray from:firstIndex to:firstIndex + n - 1 put:nil.
   644     newFirstIndex := firstIndex + n.
   640     firstIndex := firstIndex + n.
   645     contentsArray from:firstIndex to:newFirstIndex - 1 put:nil.
   641 
   646 
   642     firstIndex > lastIndex ifTrue:[
   647     newFirstIndex > lastIndex ifTrue:[
   643         "reset to avoid ever growing"
   648         "reset to avoid ever growing"
   644         firstIndex := 1.
   649         newFirstIndex := 1.
   645         lastIndex := 0 
   650         lastIndex := 0 
   646     ].
   651     ].
       
   652     firstIndex := newFirstIndex.
   647     ^ ret
   653     ^ ret
   648 
   654 
   649     "
   655     "
   650      (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:2; yourself 
   656      (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:2; yourself 
   651      (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:0; yourself 
   657      (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:0; yourself 
   652      OrderedCollection new removeFirst:2 
   658      OrderedCollection new removeFirst:2 
   653      (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:6 
   659      (OrderedCollection withAll:#(1 2 3 4 5)) removeFirst:6 
   654      (SortedCollection withAll:#(5 4 3 2 1)) removeFirst:2; yourself  
   660      (SortedCollection withAll:#(5 4 3 2 1)) removeFirst:2; yourself  
   655     "
   661     "
   656 
   662 
   657     "Modified: 12.4.1996 / 13:37:39 / cg"
   663     "Modified: 8.2.1997 / 19:20:18 / cg"
   658 !
   664 !
   659 
   665 
   660 removeFromIndex:startIndex toIndex:stopIndex
   666 removeFromIndex:startIndex toIndex:stopIndex
   661     "remove the elements stored under startIndex up to and including
   667     "remove the elements stored under startIndex up to and including
   662      the elements under stopIndex.
   668      the elements under stopIndex.
   663      Return the receiver.
   669      Return the receiver.
   664      Returning the receiver here is a historic leftover - it may change.
   670      Returning the receiver here is a historic leftover - it may change.
   665      Please use yourself in a cascade, if you need the receivers value
   671      Please use yourself in a cascade, if you need the receivers value
   666      when using this method."
   672      when using this method."
   667 
   673 
   668     |nDeleted|
   674     |nDeleted "{ Class: SmallInteger }" 
       
   675      newLastIndex|
   669 
   676 
   670     (startIndex < 1
   677     (startIndex < 1
   671     or:[stopIndex > self size]) ifTrue:[
   678     or:[stopIndex > self size]) ifTrue:[
   672         ^ self notEnoughElementsError
   679         ^ self notEnoughElementsError
   673     ].
   680     ].
   674 
   681 
   675     stopIndex < startIndex ifTrue:[
   682     nDeleted := stopIndex - startIndex + 1.
       
   683     nDeleted < 0 ifTrue:[
   676         "/ mhmh - what should be done here ?
   684         "/ mhmh - what should be done here ?
   677         ^ self error:'bad index range'
   685         ^ self error:'bad index range'
   678     ].
   686     ].
   679 
   687     nDeleted == 0 ifTrue:[^ self].
   680     nDeleted := stopIndex - startIndex + 1.
   688 
   681 
   689     "/
   682     "/ can be done faster, when removing the first elements
   690     "/ can be done faster, when removing the first elements
       
   691     "/
   683     startIndex == firstIndex ifTrue:[
   692     startIndex == firstIndex ifTrue:[
   684         "/ nil out (helps GC)
   693         "/ nil out (helps GC)
   685         contentsArray
   694         contentsArray
   686             from:firstIndex
   695             from:firstIndex
   687             to:firstIndex + nDeleted - 1
   696             to:firstIndex + nDeleted - 1
   688             put:nil.
   697             put:nil.
   689         firstIndex := firstIndex + nDeleted
   698         firstIndex := firstIndex + nDeleted
   690     ] ifFalse:[
   699     ] ifFalse:[
   691         "/ can be done faster, when removinf the last elements
   700         "/
       
   701         "/ can be done faster, when removing the last elements
       
   702         "/
   692         stopIndex == lastIndex ifTrue:[
   703         stopIndex == lastIndex ifTrue:[
   693             "/ nil out (helps GC)
   704             "/ nil out (helps GC)
   694             contentsArray
   705             contentsArray
   695                 from:lastIndex - nDeleted + 1
   706                 from:lastIndex - nDeleted + 1
   696                 to:lastIndex
   707                 to:lastIndex
   697                 put:nil.
   708                 put:nil.
   698             lastIndex := lastIndex - nDeleted
   709             lastIndex := lastIndex - nDeleted
   699         ] ifFalse:[
   710         ] ifFalse:[
       
   711             "/
   700             "/ must shuffle
   712             "/ must shuffle
   701             "/ TODO:
   713             "/ TODO:
   702             "/    for big collections, try to copy the smallest
   714             "/    for big collections, try to copy the smallest
   703             "/    possible number of elements
   715             "/    possible number of elements
   704 
   716 
       
   717             newLastIndex := lastIndex - nDeleted.
       
   718 
   705             contentsArray 
   719             contentsArray 
   706                 replaceFrom:(firstIndex + startIndex - 1)
   720                 replaceFrom:(firstIndex + startIndex - 1)
   707                 to:(lastIndex - nDeleted)
   721                 to:newLastIndex
   708                 with:contentsArray 
   722                 with:contentsArray 
   709                 startingAt:(firstIndex + stopIndex).
   723                 startingAt:(firstIndex + stopIndex).
   710 
   724 
   711             "/ nil out rest (helps GC)
   725             "/ nil out rest (helps GC)
   712             contentsArray
   726             contentsArray
   713                 from:(lastIndex - nDeleted + 1)
   727                 from:(newLastIndex + 1)
   714                 to:lastIndex
   728                 to:lastIndex
   715                 put:nil.
   729                 put:nil.
   716 
   730 
   717             lastIndex := lastIndex - nDeleted.
   731             lastIndex := newLastIndex.
   718         ]
   732         ]
   719     ].
   733     ].
   720 
   734 
   721     firstIndex > lastIndex ifTrue:[
   735     firstIndex > lastIndex ifTrue:[
   722         "reset to avoid ever growing"
   736         "reset to avoid ever growing"
   730      #(1 2 3 4 5 6 7 8 9) asOrderedCollection removeFromIndex:1 toIndex:3
   744      #(1 2 3 4 5 6 7 8 9) asOrderedCollection removeFromIndex:1 toIndex:3
   731      #(1 2 3 4 5 6 7 8 9) asOrderedCollection removeFromIndex:6 toIndex:9
   745      #(1 2 3 4 5 6 7 8 9) asOrderedCollection removeFromIndex:6 toIndex:9
   732      #(1 2 3 4 5) asOrderedCollection removeFromIndex:3 toIndex:6
   746      #(1 2 3 4 5) asOrderedCollection removeFromIndex:3 toIndex:6
   733     "
   747     "
   734 
   748 
   735     "Modified: 1.2.1997 / 12:53:58 / cg"
   749     "Modified: 8.2.1997 / 19:21:32 / cg"
   736 !
   750 !
   737 
   751 
   738 removeIdentical:anObject ifAbsent:exceptionBlock
   752 removeIdentical:anObject ifAbsent:exceptionBlock
   739     "remove the first element which is identical to anObject;
   753     "remove the first element which is identical to anObject;
   740      if found, remove and return it; 
   754      if found, remove and return it; 
  1615 ! !
  1629 ! !
  1616 
  1630 
  1617 !OrderedCollection class methodsFor:'documentation'!
  1631 !OrderedCollection class methodsFor:'documentation'!
  1618 
  1632 
  1619 version
  1633 version
  1620     ^ '$Header: /cvs/stx/stx/libbasic/OrderedCollection.st,v 1.59 1997-02-08 18:00:05 cg Exp $'
  1634     ^ '$Header: /cvs/stx/stx/libbasic/OrderedCollection.st,v 1.60 1997-02-08 18:22:27 cg Exp $'
  1621 ! !
  1635 ! !