OrderedCollection.st
changeset 19831 5e0f261a1daa
parent 19792 4625cef49989
child 19836 f6f451ada167
--- a/OrderedCollection.st	Fri May 13 23:48:14 2016 +0200
+++ b/OrderedCollection.st	Sat May 14 15:22:31 2016 +0200
@@ -745,22 +745,38 @@
      Return a collection containing the removed elements.
 
      Performance: 
-        this is an O(N) algorithm.
-
-        If a large number of objects is to be removed this way,
-        it may be better to rebuild a new collection via #select:,
-        since removing elements out of the middle is somewhat slow
-        due to the need to copy over remaining elements within the collection."
+        this is an O(N) algorithm (the receiver's elements are scanned once)."
 
     "/ this is a q&d implementation (possibly slow).
 
-    |removed element dstIndex|
-
-    removed := OrderedCollection new.
+    |removed element 
+     srcIndex "{ Class: SmallInteger }"
+     dstIndex "{ Class: SmallInteger }"|
 
-    dstIndex := firstIndex.
-    firstIndex to: lastIndex do:[:srcIndex |
+    "/ first search forward to the first element which has
+    "/ to be removed (meets the criteria)
+    srcIndex := firstIndex.
+    [ 
+        srcIndex > lastIndex
+        or:[ aBlock value:(contentsArray at:srcIndex) ]
+    ] whileFalse:[
+        srcIndex := srcIndex + 1.
+    ].
+    srcIndex > lastIndex ifTrue:[
+        "/ nothing removed
+        ^ #()
+    ].
+
+    "/ now srcIndex is the index of element, which is the first to be removed
+    removed := OrderedCollection new.
+    removed add:(contentsArray at:srcIndex).
+    
+    dstIndex := srcIndex.
+    srcIndex := srcIndex + 1.
+    
+    [ srcIndex <= lastIndex ] whileTrue:[
         element := contentsArray at:srcIndex.
+        srcIndex := srcIndex + 1.
         (aBlock value:element) ifTrue:[
             removed add:element
         ] ifFalse:[
@@ -776,31 +792,88 @@
      |coll|
 
      coll := OrderedCollection withAll:(1 to:10).
-     Transcript showCR:(coll removeAllSuchThat:[:el | el even]).
-     Transcript showCR:coll
+     Transcript show:'removed: '; showCR:(coll removeAllSuchThat:[:el | el even]).
+     Transcript show:'coll: '; showCR:coll
     "
+
     "
      |coll1 coll2|
 
+     Transcript showCR:'no element removed:'.
+
      coll1 := OrderedCollection withAll:(1 to:1000).
-     Transcript show:'(1000) - '; showCR:(
+     Transcript show:'  (1000) - '; showCR:(
+        Time millisecondsToRun:[
+            100 timesRepeat:[ coll1 copy removeAllSuchThat:[:el | el == 500] ]
+        ]).
+
+     coll2 := OrderedCollection withAll:(1 to:10000).
+     Transcript show:'  (10000) - '; showCR:(
+        Time millisecondsToRun:[
+            100 timesRepeat:[ coll2 copy removeAllSuchThat:[:el | el == 5000] ]
+        ]).
+
+     coll2 := OrderedCollection withAll:(1 to:50000).
+     Transcript show:'  (50000) - '; showCR:(
+        Time millisecondsToRun:[
+            100 timesRepeat:[ coll2 copy removeAllSuchThat:[:el | el == 25000] ]
+        ]).
+
+     Transcript showCR:'small number of elements removed:'.
+
+     coll1 := OrderedCollection withAll:(1 to:1000).
+     Transcript show:'  (1000) - '; showCR:(
+        Time millisecondsToRun:[
+            100 timesRepeat:[ coll1 copy removeAllSuchThat:[:el | el between:500 and:550] ]
+        ]).
+
+     coll2 := OrderedCollection withAll:(1 to:10000).
+     Transcript show:'  (10000) - '; showCR:(
+        Time millisecondsToRun:[
+            100 timesRepeat:[ coll2 copy removeAllSuchThat:[:el | el between:5000 and:5050] ]
+        ]).
+
+     coll2 := OrderedCollection withAll:(1 to:50000).
+     Transcript show:'  (50000) - '; showCR:(
+        Time millisecondsToRun:[
+            100 timesRepeat:[ coll2 copy removeAllSuchThat:[:el | el between:25000 and:25050] ]
+        ]).
+
+     Transcript showCR:'many elements removed:'.
+
+     coll1 := OrderedCollection withAll:(1 to:1000).
+     Transcript show:'  (1000) - '; showCR:(
         Time millisecondsToRun:[
             100 timesRepeat:[ coll1 copy removeAllSuchThat:[:el | el even] ]
         ]).
 
      coll2 := OrderedCollection withAll:(1 to:10000).
-     Transcript show:'(10000) - '; showCR:(
+     Transcript show:'  (10000) - '; showCR:(
         Time millisecondsToRun:[
             100 timesRepeat:[ coll2 copy removeAllSuchThat:[:el | el even] ]
         ]).
 
      coll2 := OrderedCollection withAll:(1 to:50000).
-     Transcript show:'(50000) - '; showCR:(
+     Transcript show:'  (50000) - '; showCR:(
         Time millisecondsToRun:[
             100 timesRepeat:[ coll2 copy removeAllSuchThat:[:el | el even] ]
         ]).
     "
-
+    "
+                    compiled bytecode bytecode/new (no jitter)
+        no element removed:
+          (1000)  -  10          20         20
+          (10000) -  70         240        200 
+          (50000) - 390        1190        940  
+        small number of elements removed:
+          (1000)  -  10          30         20
+          (10000) - 160         300        260 
+          (50000) - 700        1540       1180
+        many elements removed:
+          (1000)  -  10          20         30
+          (10000) - 130         290        260 
+          (50000) - 720        1470       1300  
+    "    
     "Modified: 8.2.1997 / 19:19:00 / cg"
 !