--- a/Collection.st Sun Feb 10 14:54:15 2019 +0100
+++ b/Collection.st Sun Feb 10 14:54:18 2019 +0100
@@ -1,5 +1,3 @@
-"{ Encoding: utf8 }"
-
"
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
@@ -4747,7 +4745,7 @@
aStream nextPut:$)
"
- #(1 2 3 'hello' $a $ü) printOn:Transcript
+ #(1 2 3 'hello' $a $ü) printOn:Transcript
(Array new:100000) printOn:Transcript
(Array new:100000) printOn:Stdout
(Array new:100000) printString size
@@ -4845,10 +4843,270 @@
!Collection methodsFor:'queries'!
+allElementsHaveTheIdenticalValue
+ "true if all elements of the receiver have the same value"
+
+ ^ self identicalValuesComputedBy:[:el | el]
+
+ "
+ #(1 2 3 5 6 7 8 9) allElementsHaveTheIdenticalValue
+ #(1 1 1 1 1 1) allElementsHaveTheIdenticalValue
+ #(1 1 1.0 1.0 1) allElementsHaveTheIdenticalValue
+ #(1 1 1.0 1.0 1) allElementsHaveTheSameValue
+ "
+!
+
+allElementsHaveTheSameValue
+ "true if all elements of the receiver have the same value"
+
+ ^ self sameValuesComputedBy:[:el | el]
+
+ "
+ #(1 2 3 5 6 7 8 9) allElementsHaveTheSameValue
+ #(1 1 1 1 1 1) allElementsHaveTheSameValue
+ #(1 1 1.0 1.0 1) allElementsHaveTheSameValue
+ "
+
+ "Created: / 21-12-2011 / 15:54:08 / cg"
+!
+
defaultElement
^ nil
!
+identicalValuesComputedBy:aBlock
+ "true if aBlock answers identical values for all elements of the receiver"
+
+ |first valueForFirstElement|
+
+ first := true.
+ self do:[:each |
+ first ifTrue:[
+ first := false.
+ valueForFirstElement := aBlock value:each.
+ ] ifFalse:[
+ valueForFirstElement == (aBlock value:each) ifFalse:[
+ ^ false.
+ ].
+ ].
+ ].
+ ^ true
+
+ "
+ #(1 2 3 5 6 7 8 9) sameValuesComputedBy:[:el | el even]
+ #(1 1 1 1 1 1) sameValuesComputedBy:[:el | el even]
+ #(1 1 1.0 1.0 1) sameValuesComputedBy:[:el | el even]
+ #(1 3 3 15 1) sameValuesComputedBy:[:el | el even]
+ "
+
+ "Created: / 21-12-2011 / 15:59:19 / cg"
+!
+
+includes:searchedElement
+ "return true, if an element equal to the argument, searchedElement is in the collection.
+ This compares using #= (i.e. it does not look for the object itself,
+ instead, one that compares equal).
+ See #includesIdentical: when identity is asked for.
+ This is a *very* slow fallback - many subclasses redefine this for performance."
+
+ self do:[:eachElement |
+ (searchedElement = eachElement) ifTrue:[^ true].
+ ].
+ ^ false
+
+ "Modified (format): / 30-04-2016 / 17:10:22 / cg"
+!
+
+includesAll:aCollection
+ "return true if the receiver includes all elements of
+ the argument, aCollection; false if any is missing.
+ Notice: depending on the concrete collection,
+ this method may have O² runtime behavior,
+ and may be slow for big receivers/args.
+ Think about using a Set, or Dictionary."
+
+ ^ aCollection conform:[:element | (self includes:element)]
+
+ "
+ #(1 2 3 4 5 6 7) includesAll:#(1 2 3)
+ #('hello' 'there' 'world') includesAll:#('hello' 'world')
+ #(1 2 3 4 5 6 7) includesAll:#(7 8 9)
+ "
+
+ "Modified: / 13-10-2006 / 12:54:50 / cg"
+ "Modified (comment): / 03-10-2018 / 13:14:10 / Claus Gittinger"
+!
+
+includesAllKeys:aCollectionOfKeys
+ "return true if the receiver includes all keys in aCollectionOfKeys,
+ false if any is missing."
+
+ ^ aCollectionOfKeys conform:[:element | (self includesKey:element)]
+
+ "
+ #(1 2 3 4 5 6 7) includesAll:#(1 2 3)
+ #('hello' 'there' 'world') includesAll:#('hello' 'world')
+ #(1 2 3 4 5 6 7) includesAll:#(7 8 9)
+ "
+
+ "Created: / 03-10-2018 / 13:12:16 / Claus Gittinger"
+!
+
+includesAny:searchedElementsCollection
+ "return true if the receiver includes any from the argument, aCollection.
+ Return false if it includes none.
+ Uses #= (value compare)
+ Notice:
+ depending on the concrete collection,
+ this method may have O² runtime behavior,
+ and may be slow for big receivers/args.
+ Think about using a Set, or Dictionary.
+
+ Some speedup is also possible, by arranging highly
+ probable elements towards the beginning of aCollection,
+ to avoid useless searches.
+
+ Also: I am not sure, if (and if so, at which breakeven),
+ it is better to reverse the loops, and walk over the receiver's
+ elements once, walking over the searched elements in the inner loop.
+ If the receiver is large, caching effects will definitely favour this,
+ as the smaller collection might fit into the cache.
+ "
+
+ |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].
+ ].
+ ] ifFalse:[
+ searchedElementsCollection do:[:searchedElement |
+ (self includes:searchedElement) ifTrue:[^ true].
+ ].
+ ].
+ ^ false
+
+ "
+ #(1 2 3 4 5 6 7) includesAny:#(1 2 3)
+ #('hello' 'there' 'world') includesAny:#('hello' 'world')
+ #(1 2 3 4 5 6 7) includesAny:#(7 8 9)
+ #(1 2 3 4 5 6 7) includesAny:#(8 9 10)
+
+ |coll|
+ coll := (1 to:10000) asOrderedCollection.
+ Time millisecondsToRun:[
+ 1000000 timesRepeat:[ coll includesAny:#(500 600) ]
+ ].
+
+ |coll|
+ coll := (1 to:10000).
+ Time millisecondsToRun:[
+ 1000000 timesRepeat:[ coll includesAny:#(500 600) ]
+ ].
+
+ |coll|
+ coll := (1 to:10000) asOrderedCollection.
+ Time millisecondsToRun:[
+ 100000 timesRepeat:[ coll includesAny:#(-1 -10) ]
+ ].
+
+ Notice: it is redefined for string search in a subclass:
+
+ |coll|
+ coll := String new:10000 withAll:$a.
+ coll at:500 put:$b.
+ Time millisecondsToRun:[
+ 100000 timesRepeat:[ coll includesAny:'bc' ]
+ ].
+
+ |coll|
+ coll := String new:10000 withAll:$a.
+ Time millisecondsToRun:[
+ 100000 timesRepeat:[ coll includesAny:'bc' ]
+ ].
+
+ "
+
+ "Modified (comment): / 12-02-2017 / 11:47:42 / cg"
+ "Modified (comment): / 03-10-2018 / 13:15:39 / Claus Gittinger"
+!
+
+includesAnyIdentical:searchedElementsCollection
+ "return true, if the receiver includes any from the argument, aCollection.
+ Return false if it includes none.
+ Use identity compare for comparing.
+ Notice:
+ depending on the concrete collection,
+ this method may have O² runtime behavior for some subclasses
+ and may be slow for big receivers/args.
+ Think about using a Set or Dictionary.
+ Some speedup is also possible, by arranging highly
+ probable elements towards the beginning of aCollection, to avoid useless searches."
+
+ searchedElementsCollection do:[:element |
+ (self includesIdentical:element) ifTrue:[^ true].
+ ].
+ ^ false
+
+ "
+ #(1 2 3 4 5 6 7) includesAnyIdentical:#(1 2 3)
+ #('hello' 'there' 'world') includesAnyIdentical:#('hello' 'world')
+ #(1 2 3 4 5 6 7) includesAnyIdentical:#(7 8 9)
+ #(1 2 3 4 5 6 7) includesAnyIdentical:#(8 9 10)
+ "
+
+ "Modified (comment): / 30-04-2016 / 17:13:38 / cg"
+ "Modified (comment): / 03-10-2018 / 13:16:09 / Claus Gittinger"
+!
+
+includesAnyKey:aCollectionOfKeys
+ "return true if the receiver includes any key from aCollectionOfKeys,
+ false if none is present."
+
+ ^ aCollectionOfKeys contains:[:element | (self includesKey:element)]
+
+ "Created: / 03-10-2018 / 13:16:57 / Claus Gittinger"
+!
+
+includesIdentical:searchedElement
+ "return true, if the argument, searchedElement is in the collection.
+ This compares using #== (i.e. object identity).
+ See #includes: when equality is asked for.
+ This is a *very* slow fallback - many subclasses redefine this for performance."
+
+ self do:[:eachElement |
+ (searchedElement == eachElement) ifTrue:[^ true].
+ ].
+ ^ false
+
+ "Modified (comment): / 30-04-2016 / 17:10:34 / cg"
+!
+
+includesKey:aKey
+ ^ self subclassResponsibility
+
+ "Created: / 03-10-2018 / 13:13:31 / Claus Gittinger"
+!
+
+isEmpty
+ "return true, if the receiver is empty"
+
+ ^ self size == 0
+!
+
+isEmptyOrNil
+ "return true if I am nil or an empty collection - true here, if the receiver's size is 0,
+ (from Squeak)"
+
+ ^ self isEmpty
+
+ "Created: / 13.11.2001 / 13:17:12 / cg"
+ "Modified: / 13.11.2001 / 13:28:35 / cg"
+!
+
isReadOnly
"true if this is a readOnly (immutable) collection.
Q1: should this be called isImmutable?
@@ -4873,6 +5131,82 @@
^ self isReadOnly not
!
+notEmpty
+ "return true, if the receiver is not empty"
+
+ ^ self isEmpty not
+!
+
+notEmptyOrNil
+ "Squeak compatibility:
+ return true if I am neither nil nor an empty collection."
+
+ ^ self notEmpty
+!
+
+occurrencesOf:anElement
+ "return the number of occurrences of the argument, anElement in
+ the receiver. Uses #= (i.e. equality) compare."
+
+ |count "{ Class: SmallInteger }" |
+
+ count := 0.
+ self do:[:element |
+ (anElement = element) ifTrue:[
+ count := count + 1
+ ].
+ ].
+ ^ count
+!
+
+occurrencesOfAny:aCollectionOfElements
+ "return the number of occurrences of any in aCollectionOfElements in the receiver.
+ Uses #= (i.e. equality) compare.
+ Should be redefined in subclass(es) if ever used heavily."
+
+ |count "{ Class: SmallInteger }" |
+
+ count := 0.
+ aCollectionOfElements do:[:element |
+ count := count + (self occurrencesOf:element)
+ ].
+ ^ count
+
+ "
+ #(1 4 6 8 4 1) occurrencesOfAny:#(1 4)
+ #(1 4 6 8 4 1) occurrencesOfAny:#(2 5)
+ 'hello world' occurrencesOfAny:'hel'
+ "
+!
+
+sameValuesComputedBy:aBlock
+ "true if aBlock answers equal values for all elements of the receiver"
+
+ |first valueForFirstElement|
+
+ first := true.
+ self do:[:each |
+ first ifTrue:[
+ first := false.
+ valueForFirstElement := aBlock value:each.
+ ] ifFalse:[
+ valueForFirstElement = (aBlock value:each) ifFalse:[
+ ^ false.
+ ].
+ ].
+ ].
+ ^ true
+
+ "
+ #(1 2 3 5 6 7 8 9) sameValuesComputedBy:[:el | el even]
+ #(1 1 1 1 1 1) sameValuesComputedBy:[:el | el even]
+ #(1 1 1.0 1.0 1) sameValuesComputedBy:[:el | el even]
+ #(1 3 3 15 1) sameValuesComputedBy:[:el | el even]
+ "
+
+ "Created: / 21-12-2011 / 15:59:19 / cg"
+!
+
size
"return the number of elements in the receiver.
This is usually redefined in subclasses for more performance."
@@ -6022,33 +6356,6 @@
!Collection methodsFor:'testing'!
-allElementsHaveTheIdenticalValue
- "true if all elements of the receiver have the same value"
-
- ^ self identicalValuesComputedBy:[:el | el]
-
- "
- #(1 2 3 5 6 7 8 9) allElementsHaveTheIdenticalValue
- #(1 1 1 1 1 1) allElementsHaveTheIdenticalValue
- #(1 1 1.0 1.0 1) allElementsHaveTheIdenticalValue
- #(1 1 1.0 1.0 1) allElementsHaveTheSameValue
- "
-!
-
-allElementsHaveTheSameValue
- "true if all elements of the receiver have the same value"
-
- ^ self sameValuesComputedBy:[:el | el]
-
- "
- #(1 2 3 5 6 7 8 9) allElementsHaveTheSameValue
- #(1 1 1 1 1 1) allElementsHaveTheSameValue
- #(1 1 1.0 1.0 1) allElementsHaveTheSameValue
- "
-
- "Created: / 21-12-2011 / 15:54:08 / cg"
-!
-
capacity
"return the number of elements, that the receiver is prepared to take.
For most collections, this is the actual size.
@@ -6060,223 +6367,6 @@
"Modified (comment): / 17-03-2017 / 11:50:34 / stefan"
!
-identicalValuesComputedBy:aBlock
- "true if aBlock answers identical values for all elements of the receiver"
-
- |first valueForFirstElement|
-
- first := true.
- self do:[:each |
- first ifTrue:[
- first := false.
- valueForFirstElement := aBlock value:each.
- ] ifFalse:[
- valueForFirstElement == (aBlock value:each) ifFalse:[
- ^ false.
- ].
- ].
- ].
- ^ true
-
- "
- #(1 2 3 5 6 7 8 9) sameValuesComputedBy:[:el | el even]
- #(1 1 1 1 1 1) sameValuesComputedBy:[:el | el even]
- #(1 1 1.0 1.0 1) sameValuesComputedBy:[:el | el even]
- #(1 3 3 15 1) sameValuesComputedBy:[:el | el even]
- "
-
- "Created: / 21-12-2011 / 15:59:19 / cg"
-!
-
-includes:searchedElement
- "return true, if an element equal to the argument, searchedElement is in the collection.
- This compares using #= (i.e. it does not look for the object itself,
- instead, one that compares equal).
- See #includesIdentical: when identity is asked for.
- This is a *very* slow fallback - many subclasses redefine this for performance."
-
- self do:[:eachElement |
- (searchedElement = eachElement) ifTrue:[^ true].
- ].
- ^ false
-
- "Modified (format): / 30-04-2016 / 17:10:22 / cg"
-!
-
-includesAll:aCollection
- "return true if the receiver includes all elements of
- the argument, aCollection; false if any is missing.
- Notice: depending on the concrete collection,
- this method may have O² runtime behavior,
- and may be slow for big receivers/args.
- Think about using a Set, or Dictionary."
-
- ^ aCollection conform:[:element | (self includes:element)]
-
- "
- #(1 2 3 4 5 6 7) includesAll:#(1 2 3)
- #('hello' 'there' 'world') includesAll:#('hello' 'world')
- #(1 2 3 4 5 6 7) includesAll:#(7 8 9)
- "
-
- "Modified: / 13-10-2006 / 12:54:50 / cg"
- "Modified (comment): / 03-10-2018 / 13:14:10 / Claus Gittinger"
-!
-
-includesAllKeys:aCollectionOfKeys
- "return true if the receiver includes all keys in aCollectionOfKeys,
- false if any is missing."
-
- ^ aCollectionOfKeys conform:[:element | (self includesKey:element)]
-
- "
- #(1 2 3 4 5 6 7) includesAll:#(1 2 3)
- #('hello' 'there' 'world') includesAll:#('hello' 'world')
- #(1 2 3 4 5 6 7) includesAll:#(7 8 9)
- "
-
- "Created: / 03-10-2018 / 13:12:16 / Claus Gittinger"
-!
-
-includesAny:searchedElementsCollection
- "return true if the receiver includes any from the argument, aCollection.
- Return false if it includes none.
- Uses #= (value compare)
- Notice:
- depending on the concrete collection,
- this method may have O² runtime behavior,
- and may be slow for big receivers/args.
- Think about using a Set, or Dictionary.
-
- Some speedup is also possible, by arranging highly
- probable elements towards the beginning of aCollection,
- to avoid useless searches.
-
- Also: I am not sure, if (and if so, at which breakeven),
- it is better to reverse the loops, and walk over the receiver's
- elements once, walking over the searched elements in the inner loop.
- If the receiver is large, caching effects will definitely favour this,
- as the smaller collection might fit into the cache.
- "
-
- |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].
- ].
- ] ifFalse:[
- searchedElementsCollection do:[:searchedElement |
- (self includes:searchedElement) ifTrue:[^ true].
- ].
- ].
- ^ false
-
- "
- #(1 2 3 4 5 6 7) includesAny:#(1 2 3)
- #('hello' 'there' 'world') includesAny:#('hello' 'world')
- #(1 2 3 4 5 6 7) includesAny:#(7 8 9)
- #(1 2 3 4 5 6 7) includesAny:#(8 9 10)
-
- |coll|
- coll := (1 to:10000) asOrderedCollection.
- Time millisecondsToRun:[
- 1000000 timesRepeat:[ coll includesAny:#(500 600) ]
- ].
-
- |coll|
- coll := (1 to:10000).
- Time millisecondsToRun:[
- 1000000 timesRepeat:[ coll includesAny:#(500 600) ]
- ].
-
- |coll|
- coll := (1 to:10000) asOrderedCollection.
- Time millisecondsToRun:[
- 100000 timesRepeat:[ coll includesAny:#(-1 -10) ]
- ].
-
- Notice: it is redefined for string search in a subclass:
-
- |coll|
- coll := String new:10000 withAll:$a.
- coll at:500 put:$b.
- Time millisecondsToRun:[
- 100000 timesRepeat:[ coll includesAny:'bc' ]
- ].
-
- |coll|
- coll := String new:10000 withAll:$a.
- Time millisecondsToRun:[
- 100000 timesRepeat:[ coll includesAny:'bc' ]
- ].
-
- "
-
- "Modified (comment): / 12-02-2017 / 11:47:42 / cg"
- "Modified (comment): / 03-10-2018 / 13:15:39 / Claus Gittinger"
-!
-
-includesAnyIdentical:searchedElementsCollection
- "return true, if the receiver includes any from the argument, aCollection.
- Return false if it includes none.
- Use identity compare for comparing.
- Notice:
- depending on the concrete collection,
- this method may have O² runtime behavior for some subclasses
- and may be slow for big receivers/args.
- Think about using a Set or Dictionary.
- Some speedup is also possible, by arranging highly
- probable elements towards the beginning of aCollection, to avoid useless searches."
-
- searchedElementsCollection do:[:element |
- (self includesIdentical:element) ifTrue:[^ true].
- ].
- ^ false
-
- "
- #(1 2 3 4 5 6 7) includesAnyIdentical:#(1 2 3)
- #('hello' 'there' 'world') includesAnyIdentical:#('hello' 'world')
- #(1 2 3 4 5 6 7) includesAnyIdentical:#(7 8 9)
- #(1 2 3 4 5 6 7) includesAnyIdentical:#(8 9 10)
- "
-
- "Modified (comment): / 30-04-2016 / 17:13:38 / cg"
- "Modified (comment): / 03-10-2018 / 13:16:09 / Claus Gittinger"
-!
-
-includesAnyKey:aCollectionOfKeys
- "return true if the receiver includes any key from aCollectionOfKeys,
- false if none is present."
-
- ^ aCollectionOfKeys contains:[:element | (self includesKey:element)]
-
- "Created: / 03-10-2018 / 13:16:57 / Claus Gittinger"
-!
-
-includesIdentical:searchedElement
- "return true, if the argument, searchedElement is in the collection.
- This compares using #== (i.e. object identity).
- See #includes: when equality is asked for.
- This is a *very* slow fallback - many subclasses redefine this for performance."
-
- self do:[:eachElement |
- (searchedElement == eachElement) ifTrue:[^ true].
- ].
- ^ false
-
- "Modified (comment): / 30-04-2016 / 17:10:34 / cg"
-!
-
-includesKey:aKey
- ^ self subclassResponsibility
-
- "Created: / 03-10-2018 / 13:13:31 / Claus Gittinger"
-!
-
isCollection
"return true, if the receiver is some kind of collection;
true is returned here - the method is redefined from Object."
@@ -6284,22 +6374,6 @@
^ true
!
-isEmpty
- "return true, if the receiver is empty"
-
- ^ self size == 0
-!
-
-isEmptyOrNil
- "return true if I am nil or an empty collection - true here, if the receiver's size is 0,
- (from Squeak)"
-
- ^ self isEmpty
-
- "Created: / 13.11.2001 / 13:17:12 / cg"
- "Modified: / 13.11.2001 / 13:28:35 / cg"
-!
-
isNilOrEmptyCollection
"return true if I am nil or an empty collection - false here.
Obsolete, use isEmptyOrNil."
@@ -6363,82 +6437,6 @@
^ false
-!
-
-notEmpty
- "return true, if the receiver is not empty"
-
- ^ self isEmpty not
-!
-
-notEmptyOrNil
- "Squeak compatibility:
- return true if I am neither nil nor an empty collection."
-
- ^ self notEmpty
-!
-
-occurrencesOf:anElement
- "return the number of occurrences of the argument, anElement in
- the receiver. Uses #= (i.e. equality) compare."
-
- |count "{ Class: SmallInteger }" |
-
- count := 0.
- self do:[:element |
- (anElement = element) ifTrue:[
- count := count + 1
- ].
- ].
- ^ count
-!
-
-occurrencesOfAny:aCollectionOfElements
- "return the number of occurrences of any in aCollectionOfElements in the receiver.
- Uses #= (i.e. equality) compare.
- Should be redefined in subclass(es) if ever used heavily."
-
- |count "{ Class: SmallInteger }" |
-
- count := 0.
- aCollectionOfElements do:[:element |
- count := count + (self occurrencesOf:element)
- ].
- ^ count
-
- "
- #(1 4 6 8 4 1) occurrencesOfAny:#(1 4)
- #(1 4 6 8 4 1) occurrencesOfAny:#(2 5)
- 'hello world' occurrencesOfAny:'hel'
- "
-!
-
-sameValuesComputedBy:aBlock
- "true if aBlock answers equal values for all elements of the receiver"
-
- |first valueForFirstElement|
-
- first := true.
- self do:[:each |
- first ifTrue:[
- first := false.
- valueForFirstElement := aBlock value:each.
- ] ifFalse:[
- valueForFirstElement = (aBlock value:each) ifFalse:[
- ^ false.
- ].
- ].
- ].
- ^ true
-
- "
- #(1 2 3 5 6 7 8 9) sameValuesComputedBy:[:el | el even]
- #(1 1 1 1 1 1) sameValuesComputedBy:[:el | el even]
- #(1 1 1.0 1.0 1) sameValuesComputedBy:[:el | el even]
- #(1 3 3 15 1) sameValuesComputedBy:[:el | el even]
- "
-
- "Created: / 21-12-2011 / 15:59:19 / cg"
! !
!Collection methodsFor:'tracing'!