implemented removal methods in the Set class
This commit is contained in:
		| @ -705,7 +705,7 @@ class Set(Collection) | |||||||
|  |  | ||||||
| 	method initialize | 	method initialize | ||||||
| 	{ | 	{ | ||||||
| 		^self __initialize_with_size: 128. (* TODO: default initial size *) | 		^self __initialize_with_size: 1. (* TODO: default initial size *) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	method __initialize_with_size: size | 	method __initialize_with_size: size | ||||||
| @ -720,7 +720,7 @@ class Set(Collection) | |||||||
| 		| newbuc newsz ass index i | | 		| newbuc newsz ass index i | | ||||||
|  |  | ||||||
| 		(* expand the bucket *) | 		(* expand the bucket *) | ||||||
| 		newsz := bs + 128. | 		newsz := bs + 32.  ## TODO: make this sizing operation configurable. | ||||||
| 		newbuc := Array new: newsz. | 		newbuc := Array new: newsz. | ||||||
| 		i := 0. | 		i := 0. | ||||||
| 		while (i < bs) | 		while (i < bs) | ||||||
| @ -738,7 +738,7 @@ class Set(Collection) | |||||||
| 		^newbuc. | 		^newbuc. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	method __find_index: anObject | 	method __find_index_for_add: anObject | ||||||
| 	{ | 	{ | ||||||
| 		| bs ass index | | 		| bs ass index | | ||||||
|  |  | ||||||
| @ -754,12 +754,65 @@ class Set(Collection) | |||||||
| 		^index. ## the item at this index is nil. | 		^index. ## the item at this index is nil. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	method __find_index: anObject | ||||||
|  | 	{ | ||||||
|  | 		| bs ass index | | ||||||
|  |  | ||||||
|  | 		bs := self.bucket size. | ||||||
|  | 		index := (anObject hash) rem: bs. | ||||||
|  |  | ||||||
|  | 		while ((ass := self.bucket at: index) notNil) | ||||||
|  | 		{ | ||||||
|  | 			if (anObject = ass) { ^index }. | ||||||
|  | 			index := (index + 1) rem: bs. | ||||||
|  | 		}. | ||||||
|  |  | ||||||
|  | 		^Error.Code.ENOENT. | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	method __remove_at: index | ||||||
|  | 	{ | ||||||
|  | 		| bs x y i v ass z | | ||||||
|  |  | ||||||
|  | 		bs := self.bucket size. | ||||||
|  | 		v := self.bucket at: index. | ||||||
|  |  | ||||||
|  | 		x := index. | ||||||
|  | 		y := index. | ||||||
|  | 		i := 0. | ||||||
|  | 		while (i < self.tally) | ||||||
|  | 		{ | ||||||
|  | 			y := (y + 1) rem: bs. | ||||||
|  |  | ||||||
|  | 			ass := self.bucket at: y. | ||||||
|  | 			if (ass isNil) { (* done. the slot at the current index is nil *) break }. | ||||||
|  | 			 | ||||||
|  | 			(* get the natural hash index *) | ||||||
|  | 			z := (ass key hash) rem: bs. | ||||||
|  |  | ||||||
|  | 			(* move an element if necessary *) | ||||||
|  | 			if (((y > x) and ((z <= x) or (z > y))) or ((y < x) and ((z <= x) and (z > y)))) | ||||||
|  | 			{ | ||||||
|  | 				self.bucket at: x put: (self.bucket at: y). | ||||||
|  | 				x := y. | ||||||
|  | 			}. | ||||||
|  | 			 | ||||||
|  | 			i := i + 1. | ||||||
|  | 		}. | ||||||
|  | 		 | ||||||
|  | 		self.bucket at: x put: nil. | ||||||
|  | 		self.tally := self.tally - 1. | ||||||
|  | 		 | ||||||
|  | 		(* return the affected association *) | ||||||
|  | 		^v | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	method add: anObject | 	method add: anObject | ||||||
| 	{ | 	{ | ||||||
| 		| index absent bs | | 		| index absent bs | | ||||||
| 		if (anObject isNil) { ^anObject }. | 		if (anObject isNil) { ^anObject }. | ||||||
|  |  | ||||||
| 		index := self __find_index: anObject. | 		index := self __find_index_for_add: anObject. | ||||||
| 		absent := (self.bucket at: index) isNil. | 		absent := (self.bucket at: index) isNil. | ||||||
| 		self.bucket at: index put: anObject. | 		self.bucket at: index put: anObject. | ||||||
|  |  | ||||||
| @ -772,12 +825,25 @@ class Set(Collection) | |||||||
| 		^anObject. | 		^anObject. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	method remove: oldObject | ||||||
|  | 	{ | ||||||
|  | 		| index | | ||||||
|  | 		index := self __find_index: oldObject. | ||||||
|  | 		if (index isError) { ^NotFoundException signal. }. | ||||||
|  | 		^self __remove_at: index. | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	method remove: oldObject ifAbsent: anExceptionBlock | 	method remove: oldObject ifAbsent: anExceptionBlock | ||||||
| 	{ | 	{ | ||||||
|  | 		| index | | ||||||
|  | 		index := self __find_index: oldObject. | ||||||
|  | 		if (index isError) { ^anExceptionBlock value }. | ||||||
|  | 		^self __remove_at: index. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	method includes: anObject | 	method includes: anObject | ||||||
| 	{ | 	{ | ||||||
|  | 		^(self __find_index: anObject) notError. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	method isEmpty | 	method isEmpty | ||||||
| @ -785,6 +851,11 @@ class Set(Collection) | |||||||
| 		^self.tally == 0 | 		^self.tally == 0 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	method size | ||||||
|  | 	{ | ||||||
|  | 		^self.tally | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	method = aSet | 	method = aSet | ||||||
| 	{ | 	{ | ||||||
| 		ifnot (self class == aSet class) { ^false }. | 		ifnot (self class == aSet class) { ^false }. | ||||||
| @ -811,6 +882,7 @@ class AssociativeCollection(Collection) | |||||||
| { | { | ||||||
| 	var tally, bucket. | 	var tally, bucket. | ||||||
|  |  | ||||||
|  |  | ||||||
| 	method(#class) new: size | 	method(#class) new: size | ||||||
| 	{ | 	{ | ||||||
| 		^self new __initialize_with_size: size. | 		^self new __initialize_with_size: size. | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user