On Wed, 27 Aug 2003, Mark Probert wrote:

> Hi, all.
>
> Say I have a hash of 4 elements, val[1..3] and name
>
>   h["a"] = "1,2,3,fred"
>   h["b"] = "4,1,2,jack"
>   h["c"] = "3,3,4,jill"
>
> How do I define:
>
>   def sort_hash(field="val1")
>     h.each { |key, data|
>       (val1, val2, val3, name) = data.split(/,/)
>     # etc..
>   end
>
> elegantly?
>
> One possibility is to write it out to a tempfile and use
> the external `sort` command.  Is there an easy pure-ruby
> solution?
>
> TIA,

whenever i end up needing sorted hashes i ALWAYS use the rbtree package from
the raa - it is awesome.  eg:

----CUT----
#!/usr/bin/env ruby
require 'rbtree' # get this from the raa - it's FAST and always sorted

class DB < RBTree
  attr :pks
  alias pk pks
  attr :fields
  attr :n_pks
  attr :n_fields
  attr :indices
  def initialize args
    @pks = (args[:pks] or args[:pk]).to_a
    @fields = args[:fields].to_a
    pks.map{|k| raise unless fields.include? k}
    @n_pks = pks.size
    @n_fields = fields.size
    @indices = {}
    fields.map{|f| indices[f] = RBTree.new}
  end
  def []= k, v
    k, v = [k, v].map{|a| a.to_a}
    raise unless k.size == pk.size and v.size == fields.size
    # map each field back to this k->v pair...
    @fields.each_with_index{|f,i| indices[f][v[i]] = [k,v]}
    super k, v
  end
  def sorted_by field
    raise unless block_given?
    indices[field].map{|k,v| yield k, v}
  end
end


db = DB.new :pk => 'f0', :fields => ['f0', 'f1', 'f2']

db['a'] = '0', 'C', 'b'
db['b'] = '1', 'B', 'a'
db['c'] = '2', 'A', 'c'

puts '--'
db.sorted_by('f0') do |k,v|
  p v
end

puts '--'
db.sorted_by('f1') do |k,v|
  p v
end

puts '--'
db.sorted_by('f2') do |k,v|
  p v
end

__END__
OUTPUT:
--
[["a"], ["0", "C", "b"]]
[["b"], ["1", "B", "a"]]
[["c"], ["2", "A", "c"]]
--
[["c"], ["2", "A", "c"]]
[["b"], ["1", "B", "a"]]
[["a"], ["0", "C", "b"]]
--
[["b"], ["1", "B", "a"]]
[["a"], ["0", "C", "b"]]
[["c"], ["2", "A", "c"]]
----CUT----

-a
  ====================================
  | Ara Howard
  | NOAA Forecast Systems Laboratory
  | Information and Technology Services
  | Data Systems Group
  | R/FST 325 Broadway
  | Boulder, CO 80305-3328
  | Email: ara.t.howard / noaa.gov
  | Phone:  303-497-7238
  | Fax:    303-497-7259
  | ~ > ruby -e 'p(%.\x2d\x29..intern)'
  ====================================