Dictionaries and Collections of keys 
Author Message
 Dictionaries and Collections of keys

In my application I generate various collections of objects which are keys to
various dictionaries.  I'm wondering what the idomatic way is of selecting all
values from a dictionary where the keys exist in another collection.

Given a dictionary of account numbers and account objects and a collection of
account numbers, what is the best (and most efficient) way to select the
dictionary's account objects?

--
.tom



Mon, 14 Jul 2003 05:55:47 GMT  
 Dictionaries and Collections of keys
Thomas,

Quote:
> Given a dictionary of account numbers and account objects and a collection
of
> account numbers, what is the best (and most efficient) way to select the
> dictionary's account object?

Here is one way -- not necessarily most efficient -- there are a lot of
variations on this theme (including inject:into:):
=======================================================================

validAccountNumbers: anAccountNumbers

    ^anAccountNumbers select: [ :each | anAccountDictionary includesKey:
each ]

accounts: anAccountNumbers

    ^( self validAccountNumbers: anAccountNumbers ) collect: [ :each |
anAccountDictionary at: each ]
=======================================================================

Here is an example that should return an OrderedCollection containing 'b'
and 'c':

| aDictionary aCollection |

aDictionary := Dictionary new: 5.
aDictionary at: 1 put: 'a'.
aDictionary at: 2 put: 'b'.
aDictionary at: 3 put: 'c'.
aDictionary at: 4 put: 'd'.
aDictionary at: 5 put: 'e'.

aCollection := OrderedCollection with: 2 with: 3.

^( aCollection select: [ :each | aDictionary includesKey: each ] ) collect:
[ :each | aDictionary at: each ]
=======================================================================

Regards,

Randy



Mon, 14 Jul 2003 11:52:09 GMT  
 Dictionaries and Collections of keys


Quote:
> In my application I generate various collections of objects which are keys
to
> various dictionaries.  I'm wondering what the idomatic way is of selecting
all
> values from a dictionary where the keys exist in another collection.

> Given a dictionary of account numbers and account objects and a collection
of
> account numbers, what is the best (and most efficient) way to select the
> dictionary's account objects?

> --
> .tom

accountDictionary
    select: [:association | accountNumberSet includes: association key]

This evaluates to a new Dictionary that contains only those accounts whose
keys are in <accountNumberSet>.

--Alan



Wed, 16 Jul 2003 19:36:01 GMT  
 Dictionaries and Collections of keys


Quote:
> In my application I generate various collections of objects which are keys to
> various dictionaries.  I'm wondering what the idomatic way is of selecting all
> values from a dictionary where the keys exist in another collection.

> Given a dictionary of account numbers and account objects and a collection of
> account numbers, what is the best (and most efficient) way to select the
> dictionary's account objects?

Using notation introduces by Randy

accounts: anAccountNumbers

     ^anAccountNumbers collect: [ :each | anAccountDictionary at: each ].

It is only one #do: run on the collection of keys.

If you need performance and you would like to go extreme you could use:

  theArray := Array new: anAccountNumbers size.  ^1 to: anAccountNumbers do:
[:i |  theArray at: i put: (anAccountDictionary at: (anAccountNumbers at:
i))].

Only primitives (except of dictionary's #at: and probably OrderedCollection's
(anAccountNumbers) #at: ).

In case of Randy's solution you run through the collection of keys twice
(even if some can get removed by checking for existance) and in Alan's
solution you can expect worse performance if the keys' collection is much
smaller than the dictionary.

Hope it helps, Jaroslaw.

Sent via Deja.com
http://www.deja.com/



Fri, 18 Jul 2003 23:52:44 GMT  
 Dictionaries and Collections of keys
Thomas,

Jaroslaw's solution will perform faster than any of the other solutions.
There seems to always be a trade-off between readability, maintainability,
and performance.  I recommed:

=======================================================================
validAccountNumbers: anAccountNumbers

    ^anAccountNumbers select: [ :each |
        anAccountDictionary includesKey: each ]

accounts: anAccountNumbers

    ^( self validAccountNumbers: anAccountNumbers ) collect: [ :each |
        anAccountDictionary at: each ]
=======================================================================

because I think it is more expressive, more understandable, and easier to
maintain than:

=======================================================================
 theArray := Array new: anAccountNumbers size.
^1 to: anAccountNumbers do: [:i |
    theArray at: i put: ( anAccountDictionary at:
        ( anAccountNumbers at: i ) ) ]
=======================================================================

But for raw speed ( assuming you decide not to build your own primitive )
the later solution will be better than the former -- thanks for pointing
that out Jaroslaw!

Regards,

Randy



Wed, 23 Jul 2003 14:35:38 GMT  
 Dictionaries and Collections of keys
Hi Randy:

<see below>

Quote:

> Thomas,

> Jaroslaw's solution will perform faster than any of the other solutions.
> There seems to always be a trade-off between readability, maintainability,
> and performance.  I recommed:

> =======================================================================
> validAccountNumbers: anAccountNumbers

>     ^anAccountNumbers select: [ :each |
>         anAccountDictionary includesKey: each ]

> accounts: anAccountNumbers

>     ^( self validAccountNumbers: anAccountNumbers ) collect: [ :each |
>         anAccountDictionary at: each ]
> =======================================================================

> because I think it is more expressive, more understandable, and easier to
> maintain than:

> =======================================================================
>  theArray := Array new: anAccountNumbers size.
> ^1 to: anAccountNumbers do: [:i |

Did you mean -  ^1 to: anAccountNumbers size  do: [:i |

???

Quote:
>     theArray at: i put: ( anAccountDictionary at:
>         ( anAccountNumbers at: i ) ) ]
> =======================================================================

> But for raw speed ( assuming you decide not to build your own primitive )
> the later solution will be better than the former -- thanks for pointing
> that out Jaroslaw!

> Regards,

> Randy

--
Thanks!!

Joseph Bacanskas [|]

--- I use Smalltalk.  My amp goes to eleven.



Thu, 24 Jul 2003 03:53:49 GMT  
 Dictionaries and Collections of keys


...

Quote:
> >  theArray := Array new: anAccountNumbers size.
> > ^1 to: anAccountNumbers do: [:i |

> Did you mean -  ^1 to: anAccountNumbers size  do: [:i |

> ???
> >     theArray at: i put: ( anAccountDictionary at:
> >         ( anAccountNumbers at: i ) ) ]

The stupid "^" is mine! :-) I have no idea how it got there. Should be:

    1 to: anAccountNumbers do: [:i |
     theArray at: i put: ( anAccountDictionary at:
         ( anAccountNumbers at: i ) ) ].
    ^theArray.

of course! With "^" it would return only the last element put into <theArray>.

Regards, Jaroslaw.

Sent via Deja.com
http://www.deja.com/



Fri, 25 Jul 2003 16:47:02 GMT  
 Dictionaries and Collections of keys
Joseph,

[snip]

Quote:
> > =======================================================================
> >  theArray := Array new: anAccountNumbers size.
> > ^1 to: anAccountNumbers do: [:i |

> Did you mean -  ^1 to: anAccountNumbers size  do: [:i |

> ???
> >     theArray at: i put: ( anAccountDictionary at:
> >         ( anAccountNumbers at: i ) ) ]
> > =======================================================================

No, I did not really mean:

^1 to: anAccountNumbers do: [:i |

I was just copying the code that Jaroslaw posted and was commenting on it
without being too picky about the code -- I figured that whoever used it
would fix it.  But here are a couple of nit-picky issues -- The original
problem was:

Quote:
> Given a dictionary of account numbers and account objects and a collection
of
> account numbers, what is the best (and most efficient) way to select the
> dictionary's account objects?

So I wrote one possible solution that combines the issues of clarity and
maintenance with some tradeoff in performance:

=======================================================================
validAccountNumbers: anAccountNumbers

    ^anAccountNumbers select: [ :each |
        anAccountDictionary includesKey: each ]

accounts: anAccountNumbers

    ^( self validAccountNumbers: anAccountNumbers ) collect: [ :each |
        anAccountDictionary at: each ]
=======================================================================

Jaroslaw correctly pointed out that there was a solution that performed
better and he provide the code:

=======================================================================
  theArray := Array new: anAccountNumbers size.
^1 to: anAccountNumbers do: [ :i |
    theArray at: i put: (anAccountDictionary at:
        (anAccountNumbers at: i))].
=======================================================================

I think what he wanted to do is:

=======================================================================
 theArray := Array new: anAccountNumbers size.
1 to: anAccountNumbers do: [ :i |
    theArray at: i put:
        ( anAccountDictionary at:
            ( anAccountNumbers at: i ) ) ].
^theArray
=======================================================================

Since the Array(Object)at:put: will return the value stored and not the new
array.  Note, additionally that the previous solution I provided handles
situations where non-existent account numbers are supplied while the
solution provided by Jaroslaw does not in its current form, but could easily
be fixed.

Regards,

Randy



Sat, 26 Jul 2003 10:49:02 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Extracting list of keys from 2-key dictionary

2. Collections/Dictionaries

3. Using NetExpress Dictionary Collection Class

4. Collection>>addAll: problems on Dictionaries

5. Multiply-keyed collection classes

6. collection class with 2 keys

7. Importing multiople keys into dictionary

8. All components of the primary key must be linked - Dictionary Relationship

9. Integer and String Dictionary Keys for Fast Access

10. Cookbook: Associating multiple values with each key in a dictionary

11. How to get a key from dictionary?

12. Regular expression as dictionary key?

 

 
Powered by phpBB® Forum Software