Sorting on hash contents

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,

···


-mark.

Apparently, Mark Probert recently 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?

Not a full answer (no time right now), but run this in irb and it should
should give you some ideas:

h = {}
h[“a”] = “1,2,3,fred”
h[“b”] = “4,1,2,jack”
h[“c”] = “3,3,4,jill”
h.to_a
h.to_a.sort_by { |el| el[1].split(/,/)[0] }
h.to_a.sort_by { |el| el[1].split(/,/)[1] }
h.to_a.sort_by { |el| el[1].split(/,/)[2] }
h.to_a.sort_by { |el| el[1].split(/,/)[3] }

Wes

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:

···

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,


[[“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)’
====================================

I notice that rbtree works with Marshal, but not YAML. What methods
would have to be added to rbtree to fix this?

Currently, RBTree would need to inherit from Hash (or) introduce custom
is_complex_yaml?, to_yaml_type and to_yaml methods.

Here’s custom methods which appear to work:

Emitting the class

class RBTree
def to_yaml_type
“!ruby/rbtree”
end
def to_yaml( opts = {} )
YAML::quick_emit( self.object_id, opts ) { |out|
out.map( to_yaml_type ) { |map|
map.concat( self.to_a )
}
}
end
end

Loading the class

YAML.add_ruby_type( ‘rbtree’ ) { |type, val|
r = RBTree.new
val.each { |k, v| r[k] = v }
r
}

Test

a = RBTree[‘ducks’, 100, ‘bears’, 12, ‘badgers’, 0]
puts a.to_yaml
p YAML::load( a.to_yaml )

Looks like…

— !ruby/rbtree
badgers: 0
bears: 12
ducks: 100

I’m not very happy with this technique though. I’d rather it was simpler,
such as:

class RBTree
include YamlHashMixin
end

_why

···

On Thursday 28 August 2003 02:27 am, Joel VanderWerf wrote:

I notice that rbtree works with Marshal, but not YAML. What methods
would have to be added to rbtree to fix this?