Hybrid hash and array?

When programming radio buttons on a website, I find myself using this
sort of construct a lot:

@choices = [
    ['1', 'Spring'],
    ['2', 'Summer'],
    ['3', 'Fall']
]

@table = {}
@choices.each do |key, value|
    @table[key] = value
end

The data structure I really want is like a hash, except that it
maintains its key/value pairs in the order that I defined them.

Or, looking at it another way, I want an array of arrays, except that
it can be accessed using the key (where the key is the first element
of each array inside the outer array).

Currently, I define it as an array of arrays, and then have a bit of
code to convert it into a hash. Then when I need it in order, I use
the array, and when I need to lookup by key, I use the hash.

Is there a built-in class that Ruby has which would automate this?

You could always use Array#assoc…

@choices.assoc(‘1’)[1] # ‘Spring’
@choices.assoc(‘3’)[1] # ‘Fall’

Hal

···

----- Original Message -----
From: “Philip Mak” pmak@aaanime.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, August 26, 2002 5:14 PM
Subject: Hybrid hash and array?

When programming radio buttons on a website, I find myself using this
sort of construct a lot:

@choices = [
    ['1', 'Spring'],
    ['2', 'Summer'],
    ['3', 'Fall']
]

@table = {}
@choices.each do |key, value|
    @table[key] = value
end

The data structure I really want is like a hash, except that it
maintains its key/value pairs in the order that I defined them.

Hi,

When programming radio buttons on a website, I find myself using this
sort of construct a lot:

@choices = [
    ['1', 'Spring'],
    ['2', 'Summer'],
    ['3', 'Fall']
]

@table = {}
@choices.each do |key, value|
    @table[key] = value
end

The data structure I really want is like a hash, except that it
maintains its key/value pairs in the order that I defined them.

Or, looking at it another way, I want an array of arrays, except that
it can be accessed using the key (where the key is the first element
of each array inside the outer array).

What about this?

require ‘delegate’

class Hash
class Ordered < DelegateClass(Hash)
def initialize(*array)
super({})
@order =
array.each(&method(:store))
end

def each
  @order.each do |key|
yield key, fetch(key)
  end
end

def store(key, val)
  has_key?(key) or @order << key
  super
end

def shift
  return if @order.empty?
  key = @order.shift
  [key, delete(key)]
end

def self.[](*array)
  new(*array)
end

end

def self.Ordered(*array)
Ordered.new(*array)
end
end

if FILE == $0
array = [
[‘3’, ‘Fall’],
[‘1’, ‘Spring’],
[‘2’, ‘Summer’],
]
nh = Hash[*array.flatten]
nh.each {|x| p x}
oh = Hash::Ordered[*array]
oh.each {|x| p x}
while x = oh.shift
p x
end
end

···

At Tue, 27 Aug 2002 07:14:19 +0900, Philip Mak wrote:


Nobu Nakada

The data structure I really want is like a hash, except that it
maintains its key/value pairs in the order that I defined them.

See this: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/20551

Find the latest here:

regards,
-joe

You could always use Array#assoc…

@choices.assoc(‘1’)[1] # ‘Spring’
@choices.assoc(‘3’)[1] # ‘Fall’

oh once again, the elusive ordered hash. :wink:

···

On Mon, 2002-08-26 at 16:26, Hal E. Fulton wrote:

----- Original Message -----
From: “Philip Mak” pmak@aaanime.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, August 26, 2002 5:14 PM
Subject: Hybrid hash and array?

When programming radio buttons on a website, I find myself using this
sort of construct a lot:

@choices = [
    ['1', 'Spring'],
    ['2', 'Summer'],
    ['3', 'Fall']
]

@table = {}
@choices.each do |key, value|
    @table[key] = value
end

The data structure I really want is like a hash, except that it
maintains its key/value pairs in the order that I defined them.

Hal


~transami

[Phillip:]
When programming radio buttons on a website, I find myself using this
sort of construct a lot:

@choices = [
    ['1', 'Spring'],
    ['2', 'Summer'],
    ['3', 'Fall']
]

@table = {}
@choices.each do |key, value|
    @table[key] = value
end

The data structure I really want is like a hash, except that it
maintains its key/value pairs in the order that I defined them.

[Hal:]
You could always use Array#assoc…

@choices.assoc(‘1’)[1] # ‘Spring’
@choices.assoc(‘3’)[1] # ‘Fall’

[Gavin:]

You can, but it’s ugly. Like Phillip, I have occasionally wanted to
retrieve hash pairs in insertion order. It seems such a simple request.
It’s not something I expect of the language, but a module would be nice.
Perl has IxHash for this. I know absolutely nothing else about it, but
maybe I’ll implement it! (Maybe it already exists on RAA, but I haven’t
seen it.)

By the way, to convert array = [[a,1], [c,2], …] to a hash, you can use:

(hang on, I thought there was a built-in way to do it in one expression -
I must be wrong)

Gavin

you may find this interesting as well, it takes the idea a step further:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/46561
i’ve started to look into an implmentation of this “Array + Hash in one”
class, but i don’t have the time.

also there is an ordered hash in the RAA:
http://www.ruby-lang.org/en/raa-list.rhtml?name=PseudoHash

~transami

···

On Mon, 2002-08-26 at 21:06, Joseph McDonald wrote:

The data structure I really want is like a hash, except that it
maintains its key/value pairs in the order that I defined them.

See this: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/20551

Find the latest here:
HTTPMail download | SourceForge.net

regards,
-joe


~transami

you may find this interesting as well, it takes the idea a step further:
  http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/46561
i've started to look into an implmentation of this "Array + Hash in one"
class, but i don't have the time.

also there is an ordered hash in the RAA:
  http://www.ruby-lang.org/en/raa-list.rhtml?name=PseudoHash

Interesting. Also, I think Judy bindings may give us nice *fast
ordered* hash functionality.

-joe