author | Stefan Vogel <sv@exept.de> |
Wed, 21 Nov 2007 18:24:07 +0100 | |
changeset 1917 | 61c602336f3d |
parent 1915 | c7fbd33fc982 |
child 1988 | ab88c724b73c |
permissions | -rw-r--r-- |
995 | 1 |
" |
2 |
COPYRIGHT (c) 2001 by eXept Software AG |
|
3 |
All Rights Reserved |
|
4 |
||
5 |
This software is furnished under a license and may be used |
|
6 |
only in accordance with the terms of that license and with the |
|
7 |
inclusion of the above copyright notice. This software may not |
|
8 |
be provided or otherwise made available to, or used by, any |
|
9 |
other person. No title to or ownership of the software is |
|
10 |
hereby transferred. |
|
11 |
" |
|
994 | 12 |
"{ Package: 'stx:libbasic2' }" |
13 |
||
14 |
Set subclass:#OrderedSet |
|
15 |
instanceVariableNames:'order' |
|
16 |
classVariableNames:'' |
|
17 |
poolDictionaries:'' |
|
18 |
category:'Collections-Sequenceable' |
|
19 |
! |
|
20 |
||
21 |
!OrderedSet class methodsFor:'documentation'! |
|
22 |
||
995 | 23 |
copyright |
24 |
" |
|
25 |
COPYRIGHT (c) 2001 by eXept Software AG |
|
26 |
All Rights Reserved |
|
27 |
||
28 |
This software is furnished under a license and may be used |
|
29 |
only in accordance with the terms of that license and with the |
|
30 |
inclusion of the above copyright notice. This software may not |
|
31 |
be provided or otherwise made available to, or used by, any |
|
32 |
other person. No title to or ownership of the software is |
|
33 |
hereby transferred. |
|
34 |
" |
|
35 |
! |
|
36 |
||
994 | 37 |
documentation |
38 |
" |
|
39 |
I am a subclass of Set whose elements are ordered in a |
|
40 |
similar fashion to OrderedCollection. |
|
41 |
That is, I have both Set behavior (only keeping a single instance of |
|
42 |
an element) but I also remember the original order, in which elements |
|
43 |
were added. |
|
44 |
||
45 |
I have one additional instance variable: |
|
46 |
||
47 |
order <OrderedCollection> Ordered collection of values reflecting the order |
|
48 |
in the set. |
|
49 |
||
50 |
[author:] |
|
51 |
Claus Gittinger |
|
52 |
||
53 |
[see also:] |
|
54 |
OrderedCollection |
|
55 |
Dictionary OrderedDictionary |
|
56 |
Set Bag |
|
57 |
" |
|
58 |
! |
|
59 |
||
60 |
examples |
|
61 |
" |
|
996 | 62 |
[exBegin] |
994 | 63 |
|s| |
64 |
||
65 |
s := OrderedSet new. |
|
66 |
s add:'one'. |
|
67 |
s add:'two'. |
|
68 |
s add:'one'. |
|
69 |
s add:'two'. |
|
70 |
s add:'three'. |
|
71 |
s size. |
|
72 |
s do:[:each | Transcript showCR:each]. |
|
996 | 73 |
[exEnd] |
74 |
||
75 |
||
76 |
[exBegin] |
|
77 |
|s| |
|
78 |
||
79 |
s := OrderedSet new. |
|
80 |
s add:'one'. |
|
81 |
s add:'two'. |
|
82 |
s add:'one'. |
|
83 |
s add:'two'. |
|
84 |
s add:'three'. |
|
85 |
s remove:'one'. |
|
86 |
s size. |
|
87 |
s do:[:each | Transcript showCR:each]. |
|
88 |
[exEnd] |
|
1581 | 89 |
|
90 |
[exBegin] |
|
91 |
|s| |
|
92 |
||
93 |
s := OrderedSet new. |
|
94 |
s add:'one'. |
|
95 |
s addFirst:'two'. |
|
96 |
s addFirst:'three'. |
|
97 |
s add:'one'. |
|
98 |
s add:'two'. |
|
99 |
s add:'three'. |
|
100 |
s size. |
|
101 |
s do:[:each | Transcript showCR:each]. |
|
102 |
[exEnd] |
|
994 | 103 |
" |
104 |
! ! |
|
105 |
||
106 |
!OrderedSet class methodsFor:'instance creation'! |
|
107 |
||
108 |
new |
|
1571 | 109 |
^super new initializeOrder |
994 | 110 |
|
111 |
"Created: / 16.11.2001 / 10:10:37 / cg" |
|
112 |
! |
|
113 |
||
114 |
new: anInteger |
|
1571 | 115 |
^(super new: anInteger) initializeOrder |
994 | 116 |
|
117 |
"Created: / 16.11.2001 / 10:10:07 / cg" |
|
118 |
! ! |
|
119 |
||
120 |
!OrderedSet methodsFor:'accessing'! |
|
121 |
||
122 |
at:index |
|
123 |
"return the indexed instance variable with index, anInteger. |
|
124 |
Report an error, if the index is wrong." |
|
125 |
||
126 |
^ order at:index |
|
127 |
||
128 |
"Modified: / 16.11.2001 / 10:27:40 / cg" |
|
1603 | 129 |
! |
130 |
||
131 |
at:index ifAbsent:exceptionalValue |
|
132 |
"return the indexed instance variable with index, anInteger. |
|
133 |
If not present, return the value from exceptionalValue." |
|
134 |
||
135 |
^ order at:index ifAbsent:exceptionalValue |
|
136 |
||
137 |
"Modified: / 16.11.2001 / 10:27:40 / cg" |
|
994 | 138 |
! ! |
139 |
||
140 |
!OrderedSet methodsFor:'adding & removing'! |
|
141 |
||
142 |
add:anObject |
|
143 |
"Add anObject to the receiver (if not already included). |
|
1915
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
144 |
Also, remember in the order (i.e. add to the end) |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
145 |
If anAssociation is already present in the dictionary, |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
146 |
the order will not be changed. (See also: #addLast:)" |
994 | 147 |
|
1915
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
148 |
anObject isNil ifTrue:[ |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
149 |
^ self invalidElementError. |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
150 |
]. |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
151 |
(self includes:anObject) ifFalse:[ |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
152 |
super add:anObject. |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
153 |
order add:anObject. |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
154 |
]. |
1322 | 155 |
^ anObject |
156 |
! |
|
157 |
||
158 |
addFirst:anObject |
|
159 |
"Add anObject to the receiver (if not already included). |
|
160 |
Also, remember in the order (i.e. add to the beginning)" |
|
161 |
||
1441
79acac990d30
Detect (and deny) nil arguments in #add*: methods (same behavior as Set)
Stefan Vogel <sv@exept.de>
parents:
1410
diff
changeset
|
162 |
anObject isNil ifTrue:[ |
79acac990d30
Detect (and deny) nil arguments in #add*: methods (same behavior as Set)
Stefan Vogel <sv@exept.de>
parents:
1410
diff
changeset
|
163 |
^ self invalidElementError. |
79acac990d30
Detect (and deny) nil arguments in #add*: methods (same behavior as Set)
Stefan Vogel <sv@exept.de>
parents:
1410
diff
changeset
|
164 |
]. |
1322 | 165 |
(self includes:anObject) ifFalse:[ |
166 |
super add:anObject. |
|
167 |
order addFirst:anObject. |
|
168 |
]. |
|
169 |
^ anObject |
|
170 |
! |
|
171 |
||
172 |
addLast:anObject |
|
173 |
"Add anObject to the receiver (if not already included). |
|
1915
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
174 |
Also, remember in the order (i.e. add to the end) |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
175 |
If anAssociation is already present in the receiver, |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
176 |
it will be moved to the end. (See also: #add:)" |
1322 | 177 |
|
1441
79acac990d30
Detect (and deny) nil arguments in #add*: methods (same behavior as Set)
Stefan Vogel <sv@exept.de>
parents:
1410
diff
changeset
|
178 |
anObject isNil ifTrue:[ |
79acac990d30
Detect (and deny) nil arguments in #add*: methods (same behavior as Set)
Stefan Vogel <sv@exept.de>
parents:
1410
diff
changeset
|
179 |
^ self invalidElementError. |
79acac990d30
Detect (and deny) nil arguments in #add*: methods (same behavior as Set)
Stefan Vogel <sv@exept.de>
parents:
1410
diff
changeset
|
180 |
]. |
1915
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
181 |
(self includes:anObject) ifTrue:[ |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
182 |
order remove:anObject ifAbsent:[]. |
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
183 |
] ifFalse:[ |
994 | 184 |
super add:anObject. |
185 |
]. |
|
1915
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
186 |
order add:anObject. |
994 | 187 |
^ anObject |
188 |
! |
|
189 |
||
190 |
remove:oldObject ifAbsent:exceptionValueProvider |
|
191 |
"remove oldObject from the collection and return it. |
|
192 |
If it was not in the collection return the value of exceptionValueProvider. |
|
193 |
||
194 |
WARNING: do not remove elements while iterating over the receiver." |
|
195 |
||
196 |
|removedObject| |
|
197 |
||
198 |
oldObject isNil ifTrue:[^ exceptionValueProvider value]. |
|
199 |
(self includes:oldObject) ifFalse:[^ exceptionValueProvider value]. |
|
200 |
||
201 |
removedObject := super remove:oldObject |
|
202 |
ifAbsent:[ ^ exceptionValueProvider value]. |
|
203 |
order removeIdentical:removedObject. |
|
204 |
||
205 |
^ removedObject |
|
206 |
||
207 |
"Modified: / 16.11.2001 / 10:21:07 / cg" |
|
208 |
! |
|
209 |
||
210 |
removeAll |
|
211 |
"remove all elements from the receiver. Returns the receiver." |
|
212 |
||
213 |
super removeAll. |
|
214 |
order := OrderedCollection new. |
|
215 |
||
216 |
"Created: / 16.11.2001 / 10:21:40 / cg" |
|
217 |
! |
|
218 |
||
1321 | 219 |
removeFirst |
220 |
"remove the first object from the collection and return it. |
|
221 |
If it was not in the collection, raise an error. |
|
222 |
||
223 |
WARNING: do not remove elements while iterating over the receiver." |
|
224 |
||
225 |
^ self removeFirstIfAbsent:[self emptyCollectionError]. |
|
226 |
! |
|
227 |
||
228 |
removeFirstIfAbsent:exceptionalValue |
|
229 |
"remove the first object from the collection and return it. |
|
230 |
If it was not in the collection, return the value from exceptionalValue. |
|
231 |
||
232 |
WARNING: do not remove elements while iterating over the receiver." |
|
233 |
||
234 |
|element| |
|
235 |
||
236 |
order isEmpty ifTrue:[^ exceptionalValue value]. |
|
237 |
element := order first. |
|
238 |
^ self remove:element. |
|
239 |
! |
|
240 |
||
1066 | 241 |
removeLast |
242 |
"remove the last object from the collection and return it. |
|
243 |
If it was not in the collection, raise an error. |
|
244 |
||
245 |
WARNING: do not remove elements while iterating over the receiver." |
|
246 |
||
247 |
^ self removeLastIfAbsent:[self emptyCollectionError]. |
|
248 |
! |
|
249 |
||
250 |
removeLastIfAbsent:exceptionalValue |
|
251 |
"remove the last object from the collection and return it. |
|
252 |
If it was not in the collection, return the value from exceptionalValue. |
|
253 |
||
254 |
WARNING: do not remove elements while iterating over the receiver." |
|
255 |
||
256 |
|lastElement| |
|
257 |
||
258 |
order isEmpty ifTrue:[^ exceptionalValue value]. |
|
259 |
lastElement := order last. |
|
260 |
^ self remove:lastElement. |
|
261 |
! |
|
262 |
||
994 | 263 |
saveRemove:oldObject |
264 |
"remove the element, oldObject from the collection. |
|
265 |
Return the element |
|
266 |
(could be non-identical to oldObject, since I hash on equality, not on identity). |
|
267 |
If it was not in the collection return nil. |
|
268 |
||
269 |
In contrast to #remove:, this does not resize the underlying collection |
|
270 |
and therefore does NOT rehash & change the elements order. |
|
271 |
Therefor this can be used while enumerating the receiver, |
|
272 |
which is not possible if #remove: is used. |
|
273 |
||
274 |
WARNING: since no resizing is done, the physical amount of memory used |
|
275 |
by the container remains the same, although the logical size shrinks. |
|
276 |
You may want to manually resize the receiver using #emptyCheck. |
|
277 |
(after the loop)" |
|
278 |
||
279 |
|removedObject| |
|
280 |
||
281 |
removedObject := super saveRemove:oldObject. |
|
282 |
removedObject notNil ifTrue:[ |
|
283 |
order removeIdentical:removedObject. |
|
284 |
]. |
|
285 |
^ removedObject |
|
286 |
||
287 |
"Created: / 16.11.2001 / 10:23:48 / cg" |
|
288 |
"Modified: / 16.11.2001 / 10:24:03 / cg" |
|
289 |
! ! |
|
290 |
||
291 |
!OrderedSet methodsFor:'copying'! |
|
292 |
||
293 |
postCopy |
|
294 |
"have to copy the keyArray too" |
|
295 |
||
296 |
super postCopy. |
|
297 |
order := order copy. |
|
298 |
||
299 |
"Created: / 16.11.2001 / 10:28:50 / cg" |
|
300 |
! ! |
|
301 |
||
302 |
!OrderedSet methodsFor:'enumerating'! |
|
303 |
||
304 |
do:aBlock |
|
305 |
"Evaluate aBlock for each of the sets's values." |
|
306 |
||
307 |
order do:[:val | aBlock value:val ] |
|
308 |
||
309 |
"Modified: / 16.11.2001 / 10:04:00 / cg" |
|
310 |
! ! |
|
311 |
||
1410 | 312 |
!OrderedSet methodsFor:'enumerting & searching'! |
313 |
||
314 |
indexOf:anObject |
|
315 |
||
316 |
^ order indexOf:anObject. |
|
317 |
! ! |
|
318 |
||
994 | 319 |
!OrderedSet methodsFor:'initialization'! |
320 |
||
1571 | 321 |
initializeOrder |
994 | 322 |
order := OrderedCollection new |
323 |
||
324 |
"Created: / 16.11.2001 / 10:06:05 / cg" |
|
325 |
! ! |
|
326 |
||
327 |
!OrderedSet class methodsFor:'documentation'! |
|
328 |
||
329 |
version |
|
1915
c7fbd33fc982
Clean up code and document differences between #add: and #addLast:
Stefan Vogel <sv@exept.de>
parents:
1603
diff
changeset
|
330 |
^ '$Header: /cvs/stx/stx/libbasic2/Attic/OrderedSet.st,v 1.13 2007-11-21 17:24:02 stefan Exp $' |
994 | 331 |
! ! |