#BUGFIX by stefan
class: StringCollection
added:
#collect:
#collect:thenSelect:
#select:thenCollect:
changed:
#asString
#copyEmpty:
#copyEmptyAndGrow:
class: StringCollection class
added: #newWithCapacity:
1. collect:... now returns an OrderedCollection, if there are elements which are non-strings.
2. printString/asString does not DNU, if there are non-string elements in StringCollection
--- a/StringCollection.st Thu Sep 21 15:27:23 2017 +0200
+++ b/StringCollection.st Thu Sep 21 15:58:22 2017 +0200
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
@@ -95,6 +97,18 @@
"
!
+newWithCapacity:size
+ "return a new empty string collection with size capacity"
+
+ ^ super new:size.
+
+ "
+ StringCollection newWithCapacity:10
+ "
+
+ "Created: / 21-09-2017 / 15:37:49 / stefan"
+!
+
newWithSize:size
"return a new string collection with size empty lines"
@@ -106,11 +120,23 @@
asString
"return myself as a string with embedded cr's"
- ^ self
- asStringWith:Character cr
- from:1 to:(self size)
- compressTabs:false
- final:Character cr
+ ^ [
+ self
+ asStringWith:Character cr
+ from:1 to:(self size)
+ compressTabs:false
+ final:Character cr
+ ] on:ConversionError do:[:ex|
+ "non-string elements trigger a ComversionError. Fall back..."
+ super printString.
+ ].
+
+ "
+ #('This' 'is' 'some' 'text') asStringCollection asString
+ #('This' 22 'some' 'text') asStringCollection asString
+ "
+
+ "Modified (format): / 21-09-2017 / 12:52:00 / stefan"
!
asStringCollection
@@ -223,16 +249,23 @@
does allocate size nil lines (it does an implicit #grow: size).
In order to get #collect: working, we should not perform this implicit grow"
- ^ super copyEmpty:0.
+ ^ self class newWithCapacity:size.
- "Created: 14.2.1996 / 11:05:47 / stefan"
+ "Created: / 14-02-1996 / 11:05:47 / stefan"
+ "Modified: / 21-09-2017 / 15:43:49 / stefan"
!
copyEmptyAndGrow:size
"performance optimization:
- StringCollections are always grown to size after #new: / #copyEmpty:"
+ StringCollections are always grown to size after #new: (containing nil elements)"
+
+ ^ self species new:size.
- ^ super copyEmpty:size.
+ "
+ #('some' 'text' 'bla') asStringCollection copyEmptyAndGrow:20
+ "
+
+ "Modified: / 21-09-2017 / 15:46:18 / stefan"
!
withoutLeadingAndTrailingBlankLines
@@ -329,6 +362,115 @@
"
! !
+!StringCollection methodsFor:'enumerating'!
+
+collect:aBlock
+ "evaluate the argument, aBlock for every element in the collection
+ and return a collection of the results.
+
+ Redefined, to change the result collection to an OrderedCollection if
+ not all elements are valid for a StringCollection (must be string or nil)."
+
+ |newCollection newElement onlyStrings
+ start "{ Class:SmallInteger }"
+ stop "{ Class:SmallInteger }" |
+
+ onlyStrings := true. "/ ... until proven otherwise
+ newCollection := self class newWithCapacity:(self size).
+ stop := lastIndex.
+ start := firstIndex.
+ start to:stop do:[:index |
+ newElement := aBlock value:(contentsArray at:index).
+ (onlyStrings and:[newElement notNil and:[newElement isString not]]) ifTrue:[
+ onlyStrings := false.
+ newCollection := newCollection asOrderedCollection.
+ ].
+ newCollection add:newElement.
+ ].
+ ^ newCollection
+
+ "
+ #('this' 'is' 'some' nil 'text') asStringCollection collect:[:i | i]
+ #('this' true 'some' nil 'text') asStringCollection collect:[:i | i ]
+ "
+
+ "Created: / 21-09-2017 / 14:31:31 / stefan"
+ "Modified: / 21-09-2017 / 15:55:21 / stefan"
+!
+
+collect:collectBlock thenSelect:selectBlock
+ "combination of collect followed by select;
+ redefined to avoid the creation of an intermediate (garbage) collection.
+
+ Redefined, to change the result collection to an OrderedCollection if
+ not all elements are valid for a StringCollection (must be string or nil)."
+
+ |newCollection newElement onlyStrings
+ start "{ Class:SmallInteger }"
+ stop "{ Class:SmallInteger }" |
+
+ onlyStrings := true. "/ ... until proven otherwise
+ newCollection := self class newWithCapacity:(self size).
+ stop := lastIndex.
+ start := firstIndex.
+ start to:stop do:[:index |
+ newElement := collectBlock value:(contentsArray at:index).
+ (selectBlock value:newElement) ifTrue:[
+ (onlyStrings and:[newElement notNil and:[newElement isString not]]) ifTrue:[
+ onlyStrings := false.
+ newCollection := newCollection asOrderedCollection.
+ ].
+ newCollection add:newElement.
+ ]
+ ].
+ ^ newCollection
+
+ "
+ #('this' 'is' 'some' nil 'text') asStringCollection collect:[:i | i] thenSelect:[:e| e notNil]
+ #('this' true 'some' nil 'text') asStringCollection collect:[:i | i ] thenSelect:[:e| e notNil]
+ "
+
+ "Created: / 21-09-2017 / 14:34:46 / stefan"
+ "Modified: / 21-09-2017 / 15:55:05 / stefan"
+!
+
+select:selectBlock thenCollect:collectBlock
+ "combination of select followed by collect;
+ redefined to avoid the creation of an intermediate (garbage) collection.
+
+ Redefined, to change the result collection to an OrderedCollection if
+ not all elements are valid for a StringCollection (must be string or nil)."
+
+ |newCollection element newElement onlyStrings
+ start "{ Class:SmallInteger }"
+ stop "{ Class:SmallInteger }" |
+
+ onlyStrings := true. "/ ... until proven otherwise
+ newCollection := self class newWithCapacity:(self size).
+ stop := lastIndex.
+ start := firstIndex.
+ start to:stop do:[:index |
+ element := contentsArray at:index.
+ (selectBlock value:element) ifTrue:[
+ newElement := collectBlock value:element.
+ (onlyStrings and:[newElement notNil and:[newElement isString not]]) ifTrue:[
+ onlyStrings := false.
+ newCollection := newCollection asOrderedCollection.
+ ].
+ newCollection add:newElement.
+ ]
+ ].
+ ^ newCollection
+
+ "
+ #('this' 'is' 'some' nil 'text') asStringCollection select:[:e| e notNil] thenCollect:[:i | i]
+ #('this' true 'some' nil 'text') asStringCollection select:[:e| e notNil] thenCollect:[:i | i]
+ "
+
+ "Created: / 21-09-2017 / 14:42:20 / stefan"
+ "Modified: / 21-09-2017 / 15:54:33 / stefan"
+! !
+
!StringCollection methodsFor:'printing & storing'!