Arc Forumnew | comments | leaders | submitlogin
sorting table keys
3 points by bOR_ 5886 days ago | 6 comments
Was trying to get the keys of a table of mine sorted, and searched google for a way to do it. This webpage quoted a bit from the arc tutorial that I had almost forgotten (about using alists rather than tables when you want sorting), and disputes that you can't sort tables.

  http://rondam.blogspot.com/2008/01/my-take-on-arc.html
  First, hash tables can be sorted, at least in the sense
  that associated lists can be sorted. Just get a list of 
  the keys and sort them. Or create a sorted-hash-table that
  maintains an adjunct sorted list of keys. This is not 
  rocket science. But that is not the problem.

Should I just switch to using alists?, I tried sorting (keys tablename) see below, but that gave an error.

  arc> (keys craa!eltm)
  (#\T #\p (bite #\p) (bite #\f) (bite #\P) (bite #\R) (bite #\S) (bite #\T) #\f #\B (bite #\B) #\P #\R #\S)
  arc> (sort < (keys craa!eltm))
  Error: "<: expects type <real number> as 2nd argument, given: #\\p; other arguments were: (bite #\\p)"
(I'm now in the phase of pretty-printing the first results. Should have a blog entry up soon enough to show you what I'm using arc for, and I'm posting a bit more then I'd normally do on the forum to get rid of the ghost-town feeling mentioned earlier by someone else ;))


3 points by almkglor 5886 days ago | link

Err. How do you expect the keys to be sorted? Is #\p < (bite #\p) ? You have to specify your own sort function, replacing < with a (fn (a b) ...) specifying how you want it to be sorted.

-----

1 point by bOR_ 5886 days ago | link

That points me in the right direction at least. I'd have wanted that everything in the list is just seen as a string, so "#\p" would indeed be smaller than "(bite #\p)" if the character "#" has a lower ascii code than "(".

coerce looked promising, but i'm not sure how to force a list like (bite #\p) into the string "(bite #\p)".

  (#\T #\p (bite #\p) (bite #\f) (bite #\P) (bite #\R) (bite #\S) (bite #\T) #\f #\B (bite #\B) #\P #\R #\S)
  (map [coerce _ 'string ] (keys craa!eltm))

  arc> (map [coerce _ 'string ] (list #\T #\p #\f))
  ("T" "p" "f")

-----

1 point by absz 5886 days ago | link

The best way to do this is

  (sort (fn (a b)
          (< (tostring:write a)
             (tostring:write b)))
        (keys the-table))
; write will print the list, in that format, to stdout, and tostring captures stdout and puts it in a string, which it returns.

-----

1 point by bOR_ 5886 days ago | link

works like a charm. thanks!

-----

1 point by bOR_ 5886 days ago | link

Hmm. printf-like control seems to be a bit of a challenge too. I'll leave it for the moment :).

-----

1 point by bOR_ 5886 days ago | link

not exactly printf, but at least I can space my output with this :)

  (def space (body spacing) (+ (newstring (- spacing (len (tostring:disp body))) #\space) (tostring:disp body)))

-----