Bag.st
author claus
Thu, 02 Jun 1994 18:22:49 +0200
changeset 88 81dacba7a63a
parent 54 06dbdeeed4f9
child 92 0c73b48551ac
permissions -rw-r--r--
*** empty log message ***

"
 COPYRIGHT (c) 1991 by Claus Gittinger
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

Collection subclass:#Bag
       instanceVariableNames:'contents'
       classVariableNames:''
       poolDictionaries:''
       category:'Collections-Unordered'
!

Bag comment:'
COPYRIGHT (c) 1991 by Claus Gittinger
              All Rights Reserved
'!

!Bag class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1991 by Claus Gittinger
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

version
"
$Header: /cvs/stx/stx/libbasic/Bag.st,v 1.7 1994-06-02 16:19:21 claus Exp $
"
!

documentation
"
    Bag implements collections whose elements are unordered and have no
    external keys. Elements may occur more than once. The implementation
    uses a dictionary to store the objects occurence count using the object
    as key (i.e. using = and hash for inclusion tests).

    Instance variables:

    contents        <Dictionary>    for each element, the number of occurrences
"
! !

!Bag class methodsFor:'instance creation'!

new
    "return a new empty Bag"

    ^ super new initContents
!

new:size
    "return a new empty Bag with initial space for size elements"

    ^ super new initContents:size
! !

!Bag methodsFor:'private'!

initContents
    "set the contents to be an empty Dictionary"

    contents := Dictionary new
!

initContents:size
    "set the contents to be an empty Dictionary with initial size"

    contents := Dictionary new:size
! !

!Bag methodsFor:'accessing'!

at:index
    "report an error: at: is not allowed for Bags"

    ^ self errorNotKeyed
!

at:index put:anObject
    "report an error: at:put: is not allowed for Bags"

    ^ self errorNotKeyed
! !

!Bag methodsFor:'testing'!

size
    "return the number of bag elements"

    |count|

    count := 0.
    contents do:[:element | count := count + element].
    ^ count
!

occurrencesOf:anObject
    "return how many times anObject is in the receiver"

    ^ contents at:anObject ifAbsent:[0]
!

includes:anObject
    "return true, if anObject is in the receiver"

    ^ contents includesKey:anObject
! !

!Bag methodsFor:'converting'!

asBag
    "return the receiver as a bag"

    "could be an instance of a subclass..."
    self class == Bag ifTrue:[
        ^ self
    ].
    ^ super asBag
! !

!Bag methodsFor:'adding & removing'!

add:newObject
    "add the argument, anObject to the receiver"

    |n|

    n := contents at:newObject ifAbsent:[0].
    contents at:newObject put:(n + 1).
    ^ newObject
!

add:newObject withOccurences:anInteger
    "add the argument, anObject anInteger times to the receiver"

    |n|

    n := contents at:newObject ifAbsent:[0].
    contents at:newObject put:(n + anInteger).
    ^ newObject
!

remove:oldObject ifAbsent:anExceptionBlock
    "Remove oldObject from the collection and return it
     - if it was not present, return the value of the exceptionBlock."

    |count|

    count := contents at:oldObject ifAbsent:[0].
    (count == 0) ifTrue:[^ anExceptionBlock value].
    (count == 1) ifTrue:[
        contents removeKey:oldObject
    ] ifFalse:[ 
        contents at:oldObject put:(count - 1)
    ].
    ^ oldObject
! !

!Bag methodsFor:'enumerating'!

do:aBlock
    "Perform the block for all members in the collection."

    contents keysAndValuesDo:[:key :value|
        value timesRepeat:[
            aBlock value:key
        ]
    ]
! !