how to sort by key a Dictionary object?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

how to sort by key a Dictionary object?

r00t uk
Hello All

I have a Dictionary object containing key value objects.  I want to be able to retrieve the key-values by sort order on the key field.  Any ideas or pointers would be greatly appreciated.  At the moment everything is being returned unsorted.

The key field is a year date and the value a URL to that year's archive.

Thanks in advance for the information.


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: how to sort by key a Dictionary object?

Randal L. Schwartz
>>>>> "r00t" == r00t uk <[hidden email]> writes:

r00t> I have a Dictionary object containing key value objects.  I want to be
r00t> able to retrieve the key-values by sort order on the key field.  Any
r00t> ideas or pointers would be greatly appreciated.  At the moment
r00t> everything is being returned unsorted.

r00t> The key field is a year date and the value a URL to that year's archive.

This might be a bit perverse, but if you flatten the dictionary into
an OrderedCollection of Associations, you can sort those:

    yourDictionary associations asSortedCollection do: [:each |
       year := each key.
       url := each value.
       ...
    ]

Browse the protocol of Association to know why #< does the right
thing for a sort.

There might be a far better way.. but I found this in a few minutes.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: how to sort by key a Dictionary object?

Bert Freudenberg

On 25.08.2009, at 23:31, Randal L. Schwartz wrote:

> There might be a far better way.. but I found this in a few minutes.


Someone should make a Squeak version of

        http://xkcd.com/627/

- Bert -


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: how to sort by key a Dictionary object?

r00t uk
Thanks Randal!  Your answer did the trick.

Bert - I don't think creating a Squeak version of that would have helped anybody new to squeak/smalltalk.  Cookbook wiki maybe?


2009/8/25 Bert Freudenberg <[hidden email]>

On 25.08.2009, at 23:31, Randal L. Schwartz wrote:

There might be a far better way.. but I found this in a few minutes.


Someone should make a Squeak version of

       http://xkcd.com/627/

- Bert -


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: how to sort by key a Dictionary object?

Bert Freudenberg
On 25.08.2009, at 23:52, r00t uk wrote:

Bert - I don't think creating a Squeak version of that would have helped anybody new to squeak/smalltalk.

Right, in this case not, but that's not what I meant primarily. Should have changed the subject and moved to squeak-dev, sorry. I'll make up for it, see below [*].

I meant that I've never seen a graphical explanation of what Randal did in these "few minutes" to find out. It's what experienced Smalltalkers do all the time, and Squeak provides powerful ways of finding out about itself, but they are not obvious to newbies.

Usually we don't even mention that it took us a minute to find out, so beginners get the impression that it's "all in our heads". It's not (not *all* anyway) but the tools allow us to find out quickly. Faster than looking up documentation indeed, which we can't really proof because of the lack of it ;)

  Cookbook wiki maybe?


2009/8/25 Bert Freudenberg <[hidden email]>

On 25.08.2009, at 23:31, Randal L. Schwartz wrote:

There might be a far better way.. but I found this in a few minutes.


Someone should make a Squeak version of

       http://xkcd.com/627/

- Bert -



[*] Here's what I'd do:

Make a little test case in a workspace:

| dict |
dict := {'a' -> 'first'. 'b' -> 'second'. 'c' ->'third'} as: Dictionary.
dict 

This intentionally does not use integers as keys, because that's what's special about Dictionaries. (and in fact I didn't really open a workspace but typed it right in the browser I happened to have open. Saves a second)

When I printed the expression above, the elements *were* sorted by key. So this may be chance, but I wanted to see. So I double-clicked Dictionary, pressed cmd-b to bring up a browser, clicked in the right pane with all the methods, and pressed p, to find printing-related methods (I should have clicked the "printing" protocol but usually methods are named more sanely than they are categorized). Anyway this took me right to the "printElementsOn: aStream" which indeed sorts. That could be a template for your own solution.

But in any case the print string of the dictionary is not helpful to show the problem. So:

| dict |
dict := {'a' -> 'first'. 'b' -> 'second'. 'c' ->'third'} as: Dictionary.
dict asArray

Yes, this printed #('second' 'third' 'first'), so now we need to sort. I have the idiom in my head but I typed in in anyway to verify

| dict  |
dict := {'a' -> 'first'. 'b' -> 'second'. 'c' ->'third'} as: Dictionary.
dict keys asSortedCollection collect: [:key | dict at: key]

And this indeed gives  an OrderedCollection('first' 'second' 'third')

So if I had sent an answer to your question I probably would have just pasted the line

dict keys asSortedCollection collect: [:key | dict at: key]

not even mentioning that it took me a minute to verify, and that en passant I discovered that dictionary printing is sorted for a couple of years already, which I had not noticed ;)

Comparing this to Randal's suggestion I'd say that mine feels more "Smalltalky". Accessing the associations in a dictionary directly feels unclean. Maybe because it breaks the abstraction, associations are an implementation detail of dictionaries. It's unlikely this will ever change and accessing the associations is fine, but still ;)

- Bert -

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: how to sort by key a Dictionary object?

Kirk Fraser
In reply to this post by r00t uk
I know this was already covered but to simplify the explination for the beginner:
 
Sort is automatic for Dictionaries.
 
| dict |
dict := Dictionary new.
dict at: '3c' put: 'object 3c'.
dict at: '1a' put: 'object 1a'.
dict at: '2b' put: 'object 2b'.
dict
 
Evaluating the code with "Print It" will respond:
a Dictionary('1a'->'object 1a' '2b'->'object 2a' '3c'->'object 3a' )
 
----------------------
 
A useful capability of Dictionaries is merging files by key.
Add old objects then overwriting with new objects and sorting is automatic.
 
| dict |
dict := Dictionary new.
dict at: '3c' put: 'object 3c'.
dict at: '1a' put: 'object 1a'.
dict at: '3c' put: 'new object 3c'.
dict
 
 a Dictionary('1a'->'object 1a' '3c'->'new object 3c' )
 

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: how to sort by key a Dictionary object?

Kirk Fraser
Opps!  An early morning typo.
 
The correct sorted answer is:
 
a Dictionary('1a'->'object 1a' '2b'->'object 2b' '3c'->'object 3c' )

On Wed, Aug 26, 2009 at 3:58 AM, Overcomer Man <[hidden email]> wrote:
I know this was already covered but to simplify the explination for the beginner:
 
Sort is automatic for Dictionaries.
 
| dict |
dict := Dictionary new.
dict at: '3c' put: 'object 3c'.
dict at: '1a' put: 'object 1a'.
dict at: '2b' put: 'object 2b'.
dict
 
Evaluating the code with "Print It" will respond:
a Dictionary('1a'->'object 1a' '2b'->'object 2a' '3c'->'object 3a' )
 
----------------------
 
A useful capability of Dictionaries is merging files by key.
Add old objects then overwriting with new objects and sorting is automatic.
 
| dict |
dict := Dictionary new.
dict at: '3c' put: 'object 3c'.
dict at: '1a' put: 'object 1a'.
dict at: '3c' put: 'new object 3c'.
dict
 
 a Dictionary('1a'->'object 1a' '3c'->'new object 3c' )
 

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: how to sort by key a Dictionary object?

Bert Freudenberg
In reply to this post by Kirk Fraser

On 26.08.2009, at 12:58, Overcomer Man wrote:

I know this was already covered but to simplify the explination for the beginner:
 
Sort is automatic for Dictionaries.

This is over-simplifying. *Printing* of dictionaries sorts automatically. But not regular iteration.

- Bert -



_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: how to sort by key a Dictionary object?

Randal L. Schwartz
>>>>> "Bert" == Bert Freudenberg <[hidden email]> writes:

Bert> On 26.08.2009, at 12:58, Overcomer Man wrote:

>> I know this was already covered but to simplify the explination for  the
>> beginner:
>>
>> Sort is automatic for Dictionaries.

Bert> This is over-simplifying. *Printing* of dictionaries sorts  automatically. But
Bert> not regular iteration.

And this is because #printOn: contains sorting code:

    "Collection >> #printOn:"
    printOn: aStream
      "Append a sequence of characters that identify the receiver to aStream."

      self printNameOn: aStream.
      self printElementsOn: aStream

which further calls:

    "Dictionary >> #printElementsOn:"
    printElementsOn: aStream
      aStream nextPut: $(.
      self size > 100
      ifTrue: [aStream nextPutAll: 'size '.
        self size printOn: aStream]
      ifFalse: [self keysSortedSafely
        do: [:key | aStream print: key;
          nextPutAll: '->';            
          print: (self at: key);
          space]].
      aStream nextPut: $)

Note the "self keysSortedSafely".  This is another strategy for
walking a dictionary in key order.

As we were discussing this issue last night at the Portland Smalltalk meeting
after-meeting dinner, whether it is faster to grab the associations to sort
them, or to grab the keys to sort them first then go look up the values,
depends on the storage of a Dictionary.  And I suspect that since the Squeak
implementation of Dictionary already has the associations and just needs to
spit them out, that's probably going to be faster than going back to look
them up one by one, as the above code does.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: how to sort by key a Dictionary object?

Bert Freudenberg

On 26.08.2009, at 16:50, Randal L. Schwartz wrote:

> As we were discussing this issue last night at the Portland  
> Smalltalk meeting
> after-meeting dinner, whether it is faster to grab the associations  
> to sort
> them, or to grab the keys to sort them first then go look up the  
> values,
> depends on the storage of a Dictionary.  And I suspect that since  
> the Squeak
> implementation of Dictionary already has the associations and just  
> needs to
> spit them out, that's probably going to be faster than going back to  
> look
> them up one by one, as the above code does.


This is leaving newbie-territory, but don't speculate about  
performance, measure instead:

| dict |
dict := Dictionary new.
100000 timesRepeat: [dict at: 1000000 atRandom put: 'dummy'].
{
[dict keys asSortedCollection do: [:key | | value | value := dict at:  
key]] timeToRun.
[dict associations asSortedCollection do: [:assoc | | key value |  
key := assoc key. value := assoc value]] timeToRun.
}

... and this would give the advantage to using #keys.

- Bert -


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: how to sort by key a Dictionary object?

Randal L. Schwartz
>>>>> "Bert" == Bert Freudenberg <[hidden email]> writes:

Bert> ... and this would give the advantage to using #keys.

Fascinating.  I suppose it's all those extra calls to extract the key
from the association during the sort.

In this case, it's the inverse of the Schwartzian Transform. :)

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: how to sort by key a Dictionary object?

Bert Freudenberg

On 26.08.2009, at 17:31, Randal L. Schwartz wrote:

>>>>>> "Bert" == Bert Freudenberg <[hidden email]> writes:
>
> Bert> ... and this would give the advantage to using #keys.
>
> Fascinating.  I suppose it's all those extra calls to extract the key
> from the association during the sort.

You're speculating again ;)

> In this case, it's the inverse of the Schwartzian Transform. :)
>
> --  
> Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503  
> 777 0095
> <[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
> See http://methodsandmessages.vox.com/ for Smalltalk and Seaside  
> discussion

- Bert -


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: how to sort by key a Dictionary object?

r00t uk
In reply to this post by Bert Freudenberg
Thanks Bert

That explanation was really useful and the length to which you went in describing the "solution" process you went through is appreciated.

Regards

2009/8/26 Bert Freudenberg <[hidden email]>
On 25.08.2009, at 23:52, r00t uk wrote:

Bert - I don't think creating a Squeak version of that would have helped anybody new to squeak/smalltalk.

Right, in this case not, but that's not what I meant primarily. Should have changed the subject and moved to squeak-dev, sorry. I'll make up for it, see below [*].

I meant that I've never seen a graphical explanation of what Randal did in these "few minutes" to find out. It's what experienced Smalltalkers do all the time, and Squeak provides powerful ways of finding out about itself, but they are not obvious to newbies.

Usually we don't even mention that it took us a minute to find out, so beginners get the impression that it's "all in our heads". It's not (not *all* anyway) but the tools allow us to find out quickly. Faster than looking up documentation indeed, which we can't really proof because of the lack of it ;)

  Cookbook wiki maybe?


2009/8/25 Bert Freudenberg <[hidden email]>

On 25.08.2009, at 23:31, Randal L. Schwartz wrote:

There might be a far better way.. but I found this in a few minutes.


Someone should make a Squeak version of

       http://xkcd.com/627/

- Bert -



[*] Here's what I'd do:

Make a little test case in a workspace:

| dict |
dict := {'a' -> 'first'. 'b' -> 'second'. 'c' ->'third'} as: Dictionary.
dict 

This intentionally does not use integers as keys, because that's what's special about Dictionaries. (and in fact I didn't really open a workspace but typed it right in the browser I happened to have open. Saves a second)

When I printed the expression above, the elements *were* sorted by key. So this may be chance, but I wanted to see. So I double-clicked Dictionary, pressed cmd-b to bring up a browser, clicked in the right pane with all the methods, and pressed p, to find printing-related methods (I should have clicked the "printing" protocol but usually methods are named more sanely than they are categorized). Anyway this took me right to the "printElementsOn: aStream" which indeed sorts. That could be a template for your own solution.

But in any case the print string of the dictionary is not helpful to show the problem. So:

| dict |
dict := {'a' -> 'first'. 'b' -> 'second'. 'c' ->'third'} as: Dictionary.
dict asArray

Yes, this printed #('second' 'third' 'first'), so now we need to sort. I have the idiom in my head but I typed in in anyway to verify

| dict  |
dict := {'a' -> 'first'. 'b' -> 'second'. 'c' ->'third'} as: Dictionary.
dict keys asSortedCollection collect: [:key | dict at: key]

And this indeed gives  an OrderedCollection('first' 'second' 'third')

So if I had sent an answer to your question I probably would have just pasted the line

dict keys asSortedCollection collect: [:key | dict at: key]

not even mentioning that it took me a minute to verify, and that en passant I discovered that dictionary printing is sorted for a couple of years already, which I had not noticed ;)

Comparing this to Randal's suggestion I'd say that mine feels more "Smalltalky". Accessing the associations in a dictionary directly feels unclean. Maybe because it breaks the abstraction, associations are an implementation detail of dictionaries. It's unlikely this will ever change and accessing the associations is fine, but still ;)

- Bert -

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners



_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners