hi 

here are the collection extensions we use in Moose.
I copied them to PharoTaskForces so that we can discuss and tweak the code if 
wanted.

My favorite is 
        flatCollect:/flatCollectAsSet: 
        groupedBy:
        
        There are really useful. 

Stef


testFlatCollectArray
        "self debug: #testFlatCollectArray"
        
        self assert: ((#((1 2) (3 4) (5 3)) flatCollect: [ :each ]) = #(1 2 3 4 
5 3)).
        self assert: ((#((1 2) (2 3) (1 3 4)) flatCollect: [:each]) = #(1 2 2 3 
1 3 4)).        
                
        self assert: ((#((1 2) (2 3) () ()) flatCollect: [:each]) = #(1 2 2 
3)). 

        self assert: ((#((1 2) (2 3) (1 3 4)) flatCollect: [:each| Array with: 
each])
                                        =  #(#(1 2) #(2 3) #(1 3 4))).
                                        
        self assert: ((#((1 2) (2 3) (1 3 4)) flatCollect: [:each| Set with: 
each])
                                        =  #(#(1 2) #(2 3) #(1 3 4))).  
        

testFlatCollectSet
        "self debug: #testFlatCollectSet"
        
        self assert: ((#((1 2) (1 2) (1 3 4)) asSet  flatCollect: [:each]) = 
#(1 1 2 3 4) asSet).
        self assert: ((#() asSet flatCollect: [:each]) = #() asSet).

        self assert:  ((#((1 2) () (1 3 4)) asSet  flatCollect: [:each]) = #(1 
1 2 3 4) asSet).
        self assert:  ((#((1 2) #((99)) (1 3 4)) asSet  flatCollect: [:each]) 
                                        = #(1 1 2 3 4 (99)) asSet).
        self assert:  ((#((1 2) #(()) (1 3 4)) asSet  flatCollect: [:each]) 
                                        = #(1 1 2 3 4 ()) asSet).

testCollectAsSet
        "self debug: #testCollectAsSet"
        
        self assert: ((#() collectAsSet: [:each | each odd]) = Set new).
        self assert: (#(1 2 3 4 5 6) collectAsSet: [:each | each odd])
                                         = (Set with: true with: false).
        self assert: (#(1 3 5 7 9 11) collectAsSet: [:each | each odd]) 
                                        = (Set with: true).
                                        
        self assert: (#(1 2 3 4 5 4 3 2 1) collectAsSet: [:each | each]) = (1 
to: 5) asSet.
        
        
testGroupedByArray
        "self debug: #testGroupedByArray"
        
        | res |
        res := #(1 2 3 4 5) groupedBy: [:each | each odd].
        self assert:   (res at: true) = #(1 3 5).
        self assert: (res at: false) = #(2 4)



Set>>flatCollect: aBlock 
        
        
        ^self flatCollectAsSet: aBlock


Symbol>>value
        "Allow this object to act as a ValueHolder on itself."

        ^self

OrderedCollection>>removeAtIndex: anIndex
        "Remove the element of the collection at position anIndex.  Answer the 
object removed."

        | obj |
        obj := self at: anIndex.
        self removeIndex: anIndex + firstIndex - 1.
        ^obj

Collection 
==============================

collectAsSet: aBlock
        "Evaluates aBlock for each element of the receiver and collects
        the resulting values into a Set."

        "This is an efficient shorthand for [ (self collect: aBlock) asSet ]."
        "originally developed by a. kuhn and released under MIT."
        
        ^self inject: Set new into: [ :set :each | 
                set add: (aBlock value: each); yourself ].


copyEmpty: aSize
        "Answer a copy of the receiver that contains no elements.

        This method should be redefined in subclasses that add
        instance variables, so that the state of those variables
        is preserved"

        ^self class new: aSize


flatCollect: aBlock 
        "Evaluate aBlock for each of the receiver's elements and answer the
        list of all resulting values flatten one level. Assumes that aBlock 
returns some kind
        of collection for each element. Equivalent to the lisp's mapcan"
        "original written by a. Kuhn and released under MIT"
        
        | stream |
        self isEmpty ifTrue: [ ^ self copy ].
        stream := (self species new: 0) nsWriteStream.
        self do: [ :each | stream nextPutAll: (aBlock value: each) ].
        ^ stream contents

flatCollectAsSet: aBlock
        "Evaluate aBlock for each of the receiver's elements and answer the
        list of all resulting values flatten one level. Assumes that aBlock 
returns some kind
        of collection for each element. Equivalent to the lisp's mapcan"
        
        "original written by a. Kuhn and released under MIT"
        
        | set |
        self isEmpty ifTrue: [^self copy ].
        set := Set new.         
        self do: [ :each |
                set addAll: (aBlock value: each) ].
        ^set


flatten
        "Recursively collect each non-collection element of the receiver and 
its descendant
        collections.  Please note, this implementation assumes that strings are 
to be treated
        as objects rather than as collection."

        ^self gather: [ :each ]

groupedBy: aBlock
        "Return a dictionary whose keys are the result of evaluating aBlock for 
all elements in
         the collection, and the value for each key is the collection of 
elements that evaluated
         to that key. e.g.
             #(1 2 3 4 5) groupedBy: [:each | each odd]
           a Dictionary  
             true ---> #( 1 3 5)
             false --> #(2 4)
        originally developed by a. kuhn and released under MIT."

        | result |
        result := Dictionary new.
        self do:
                [:each | | key collection |
                key := aBlock value: each.
                collection := result at: key ifAbsentPut: [OrderedCollection 
new].
                collection add: each].
        self species ~~ OrderedCollection ifTrue:
                ["Convert the result collections to be the right type.
                  Note that it should be safe to modify the dictionary
                  while iterating because we only replace values for existing 
keys"
                result keysAndValuesDo:
                        [:key :value | result at: key put: (self species 
withAll: value)]].

        ^result

includesAll: aCollection 
        "Answer true if the receiver includes all elements of aCollection with 
at
        least as many occurrences as in aCollection. For a less strict 
comparison
        please refer to supersetOf: and its inverse subsetOf:."


        ^(aCollection isCollection) and: [
                aCollection size <= self size and: [
                        aCollection allSatisfy: [ :each | 
                                (aCollection occurrencesOf: each) <= (self 
occurrencesOf: each) ]]]

nilSafeGroupedBy: aBlock
        ^ self groupedBy: [ :each |
                | value |
                value := aBlock value: each.
                value ifNil: [ UndefinedObject ].
        ]       

selectAsSet: aBlock 
        "Evaluate aBlock with each of the receiver's elements as the argument. 
        Collect into a new set, only those elements for which
        aBlock evaluates to true.  Answer the new collection."

        | newSet |
        newSet := Set new.
        self do: [:each | (aBlock value: each) ifTrue: [newSet add: each]].
        ^newSet

shuffle
        "Swaps the receiver's elements at random."

        self shuffle: (self size * self size log) asInteger

sum: aSymbolOrBlock 
         
        ^self 
                inject: 0 
                into: [:sum :each | sum + (aSymbolOrBlock value: each)]

shuffle: times
        "Swaps random elements of the receiver."

        | size random |
        size := self size.
        random := Random new.
        times timesRepeat: [ 
                self swap: (random next * size) floor + 1 with: (random next * 
size) floor + 1 
        ].




_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

Reply via email to