Collection.st
branchjv
changeset 19811 65fec19facb0
parent 19707 8e312f358d84
parent 19780 6286d1e4c360
child 20079 8d884971c2ed
--- a/Collection.st	Thu May 05 06:48:19 2016 +0200
+++ b/Collection.st	Thu May 12 09:30:28 2016 +0200
@@ -2365,12 +2365,12 @@
 
     |newCollection|
 
-    newCollection := self species new.
+    newCollection := self speciesForCollecting new:self size.
     self do:[:element | newCollection add:(aBlock value:element)].
     ^ newCollection
 
     "
-     #(1 2 3 4) collect:[:n | n * 2]  
+     #(1 2 3 4) asSet collect:[:n | n * 2]  
     "
 !
 
@@ -2555,7 +2555,7 @@
 
     |newCollection runIndex|
 
-    newCollection := self speciesForCollecting new.
+    newCollection := self speciesForCollecting new:self size.
     runIndex := 1.
     self do:[:element | 
         newCollection add:(aTwoArgBlock value:element value:runIndex).
@@ -2659,6 +2659,9 @@
     "
      #((1 'one') (2 'two') (3 'three') (4 'four')) 
         detect:[:pair | pair first odd] thenCompute:[:pair | pair second]  
+
+     #( (2 'two') (4 'four')) 
+        detect:[:pair | pair first odd] thenCompute:[:pair | pair second]  
     "
 !
 
@@ -2668,7 +2671,10 @@
      applied to the element which caused the true evaluation.
      If none of the evaluations returns true, return the value from exceptionValue."
 
-    ^ evalBlock value:(self detect:checkBlock ifNone:[^ exceptionValue value]).
+    |foundElement|
+    
+    foundElement := self detect:checkBlock ifNone:[^ exceptionValue value].
+    ^ evalBlock value:foundElement.
 
     "
      #((1 'one') (2 'two') (3 'three') (4 'four')) 
@@ -2714,7 +2720,7 @@
 !
 
 detectMax: aBlock
-    "Evaluate aBlock with each of the receiver's elements as the argument. 
+    "Evaluate aBlock with each of the receiver's elements as argument. 
      Answer the element for which aBlock evaluates to the highest magnitude.
      If the receiver collection is empty, return nil.  
      This method might also be called elect:."
@@ -2743,7 +2749,7 @@
 !
 
 detectMin: aBlock
-    "Evaluate aBlock with each of the receiver's elements as the argument. 
+    "Evaluate aBlock with each of the receiver's elements as argument. 
      Answer the element for which aBlock evaluates to the lowest number.
      If the receiver collection is empty, return nil."
 
@@ -3208,6 +3214,52 @@
     "Modified: 20.4.1996 / 11:33:50 / cg"
 !
 
+keysAndValuesDetect:aBlock ifNone:exceptionalValue
+    "for each key-value pair in the receiver, evaluate the argument, aBlock
+     and return the value for which aBlock returns true the very first time.
+     If none of the evaluations returns true, return the result of the
+     evaluation of the exceptionBlock"
+     
+    self keysAndValuesDo:[:key :value |
+        (aBlock value:key value:value) ifTrue:[^ value].
+    ].
+    ^ exceptionalValue value
+
+    "
+     |ages|
+
+     ages := Dictionary new.
+     ages at:'cg' put:37.
+     ages at:'ca' put:33.
+     ages at:'sv' put:36.
+     ages at:'tk' put:28.
+     ages keysAndValuesDetect:[:name :age | age = 33].
+    "
+!
+
+keysAndValuesDetectKey:aBlock ifNone:exceptionalValue
+    "for each key-value pair in the receiver, evaluate the argument, aBlock
+     and return the key/index for which aBlock returns true the very first time.
+     If none of the evaluations returns true, return the result of the
+     evaluation of the exceptionBlock"
+     
+    self keysAndValuesDo:[:key :value |
+        (aBlock value:key value:value) ifTrue:[^ key].
+    ].
+    ^ exceptionalValue value
+
+    "
+     |ages|
+
+     ages := Dictionary new.
+     ages at:'cg' put:37.
+     ages at:'ca' put:33.
+     ages at:'sv' put:36.
+     ages at:'tk' put:28.
+     ages keysAndValuesDetectKey:[:name :age | age = 33] ifNone:nil.
+    "
+!
+
 keysAndValuesDo:aTwoArgBlock
     "evaluate the argument, aBlock for every element in the collection,
      passing both index and element as arguments.
@@ -3337,15 +3389,17 @@
     "Modified: / 20-10-2007 / 17:17:50 / cg"
 !
 
-partition:check into:aTwoArgBlock
-    "partition the receiver elements into two sets, depending on the outcome
-     of a check block. Evaluate aTwoArgBlock on the two selected and rejected value 
-     collections. Also return the selected values as return value"
+partition:check as:species into:aTwoArgBlock
+    "enumerate the receiver's elements and partition them into two collections, 
+     depending on the outcome of a check block.
+     The type of result collection is passed in via the species argument. 
+     Evaluate aTwoArgBlock on the two selected and rejected value collections. 
+     Also return the selected values as return value"
 
     |selected rejected|
 
-    selected := OrderedCollection new.
-    rejected := OrderedCollection new. 
+    selected := species new.
+    rejected := species new. 
     self do:[:each | ((check value:each) ifTrue:[selected] ifFalse:[rejected]) add:each].
     aTwoArgBlock value:selected value:rejected.
     ^ selected
@@ -3353,6 +3407,25 @@
     "
      #(1 2 3 4 5 6 7 8)
         partition:[:el | el even]
+        as:Set    
+        into:[:evenElements :oddElements |
+            Transcript show:'even: '; showCR:evenElements.
+            Transcript show:' odd: '; showCR:oddElements.
+        ].
+    "
+!
+
+partition:check into:aTwoArgBlock
+    "enumerate the receiver's elements and partition them into two collections, 
+     depending on the outcome of a check block. 
+     Evaluate aTwoArgBlock on the two selected and rejected value collections. 
+     Also return the selected values as return value"
+
+    ^ self partition:check as:OrderedCollection into:aTwoArgBlock
+
+    "
+     #(1 2 3 4 5 6 7 8)
+        partition:[:el | el even]
         into:[:evenElements :oddElements |
             Transcript show:'even: '; showCR:evenElements.
             Transcript show:' odd: '; showCR:oddElements.
@@ -5278,13 +5351,17 @@
 
 !Collection methodsFor:'sorting & reordering'!
 
-sortedBy:aBlock
+sortedBy:aTwoArgBlock
     "Create a copy that is sorted.  Sort criteria is the block that accepts two arguments.
      When the block returns true, the first arg goes first ([:a :b | a > b] sorts in descending order)."
 
-    ^ (self asNewOrderedCollection sort: aBlock)
-
-    "Modified: / 22-10-2008 / 21:25:07 / cg"
+    |newCollection|
+
+    newCollection := self speciesForAdding new:self size.
+    self addAllTo:newCollection.
+    newCollection sort:aTwoArgBlock.
+
+    ^ newCollection
 !
 
 sortedBySelector:aSelector
@@ -5598,7 +5675,7 @@
 !
 
 includesAll:aCollection
-    "return true, if the the receiver includes all elements of
+    "return true, if the receiver includes all elements of
      the argument, aCollection; false if any is missing.
      Notice: this method has OČ runtime behavior and may be
              slow for big receivers/args. 
@@ -5631,7 +5708,12 @@
         If the receiver is large, caching effects will definitely favour this.        
     "
 
-    self size < searchedElementsCollection size ifTrue:[
+    |mySize searchedSize|
+    
+    mySize := self size.
+    searchedSize := searchedElementsCollection size.
+    "/ avoid this only for big receivers, due to caching effects
+    (mySize < searchedSize) ifTrue:[
         self do:[:existingElement |
             (searchedElementsCollection includes:existingElement) ifTrue:[^ true].
         ].
@@ -5651,8 +5733,8 @@
      |coll|
      coll := (1 to:10000) asOrderedCollection.
      Time millisecondsToRun:[
-        100000 timesRepeat:[ coll includesAny:#(500 600) ]
-     ].  
+        1000000 timesRepeat:[ coll includesAny:#(500 600) ]
+     ]. 
 
      |coll|
      coll := (1 to:10000) asOrderedCollection.