unique values in collections

Richard A. O'Keefe ok at cs.otago.ac.nz
Thu Mar 13 22:49:25 UTC 2003


Janet Abdul-Karim <jn_karim at yahoo.com> wrote:
	I have a collection [kind unspecified] of portfolios and
	each portfolio has a collection [kind unspecified] of accounts.
	I am trying to get the sum of the accounts, but my problem is if
	that some portfolios have the same account then that would not
	give me the write [sic.] sum.

	[I]s there some method to make sure all value[s] are
	unique in a collection[?]
	
First off, what does it mean to add two accounts?
I mean, if you add my account and Bill Gates', what do you get?
Is the resulting account his, mine, yours, or George Bush's?

Presumably "the sum of the accounts" means "the sum of the values of the
accounts",
    accounts inject: 0 into: [:sum :each | sum + each valueInCents]

The best way to make sure that all the objects in a collection are
unique is to ensure in your own code that you never add the same object
twice.  You can of course use a Set (or IdentitySet, or PluggableSet if
you want to use account number as the key) to hold accounts, but first
you must ask the DESIGN question:

    - is it ever meaningful for an account to belong to two portfolios?
    - if it is, what does it mean?
    - if it isn't, what does your code do to ensure it doesn't happen?

For example, you might have
    Object subclass: #Account
      instanceVariableNames: 'id valueInCents portfolio ...'

    addTo: aPortfolio
      portfolio ifNil: [^aPortfolio add: self].
      portfolio == aPortfolio
        ifFalse: [self error: 'account is already in another portfolio'].

    removeFrom: aPortfolio
      portfolio == aPortfolio
        ifFalse: [self error: 'account is not in that portfolio'].
      portfolio remove: self.
      portfolio := nil.

The simplistic solution is to suppose that you currently have something
like
    portfolios inject: 0 into: [:sum :each |
      each accounts inject: sum into: [:sum | each
        sum + each valueInCents]]
which totals the values of the accounts in all the portfolios.
You DO want to allow accounts to be in multiple portfolios, but
you only want to count each account once.

    |accountSet|
    accountSet := IdentitySet new.
    portfolios do: [:portfolio | accountSet addAll: portfolio accounts].
    total := accountSet inject: 0 into: [:sum :each | sum + each valueInCents].




More information about the Squeak-dev mailing list