Ordered hashes/ yaml?


#1

hi -

i understand hashes dont keep their order in ruby, so wondering what the
most elegant way to create some YAML that i want to maintain order is…

for a simple menu system, i have a YAML file currently as:

section1:
link1: home
link2: my page
link3: logout

section2:
… etc

but after reading in thru YAML::load this can come out as a different
order. eg the logout button first…

but to keep this as an array, it seems nasty to step thru and read
pairs/skip in twos thru the array:

section:
{ link1, home, link2, mypage … }

on the subject, what do people like as a clear examples site? the spec
does
its best to make YAML as unreadable as XML…
http://yaml.org/spec/current.html#id2540046

http://yaml4r.sourceforge.net/cookbook/
seems good

thanks!

/dc


#2

d c wrote:

i understand hashes dont keep their order in ruby, so wondering what the
most elegant way to create some YAML that i want to maintain order is…

You can monkey-patch Hash to do it:

class Hash
def to_yaml( opts = {} )
YAML::quick_emit( object_id, opts ) do |out|
out.map( taguri, to_yaml_style ) do |map|
sorted_keys = keys
sorted_keys = begin
sorted_keys.sort
rescue
sorted_keys.sort_by {|k| k.to_s} rescue sorted_keys
end

     sorted_keys.each do |k|
       map.add( k, fetch(k) )
     end
   end
 end

end
end


#3

Joel VanderWerf wrote:

You can monkey-patch Hash to do it:

Do you really use that term that way? I wince when I read it. :wink:

class Hash

[snip]

But that sorts the keys… wouldn’t he have to add a field to each
key on which to sort, if he wanted to preserve original order?

Hal


#4

Hal F. wrote:

Joel VanderWerf wrote:

You can monkey-patch Hash to do it:

Do you really use that term that way? I wince when I read it. :wink:

Hm. Ruby-quiz: find a better term…

class Hash

[snip]

But that sorts the keys… wouldn’t he have to add a field to each
key on which to sort, if he wanted to preserve original order?

Erg. It’s way too late for me to be posting. You’re quite right. All
that my simian patch does is sort in an order that is probably quite
unwanted.


#5

Trans wrote:

but to keep this as an array, it seems nasty to step thru and read
pairs/skip in twos thru the array:

YAML has a secondary type called an omap. It is supported in the syck
implementation:

That still loads as an array though:

require ‘yaml’

h = YAML.load <<EOY
section1: !omap
- link1: home
- link2: my page
- link3: logout
EOY

p h

END

Output:

{“section1”=>[[“link1”, “home”], [“link2”, “my page”], [“link3”,
“logout”]]}

Maybe the !!omap is useful, but the thing it loads as doesn’t seem to
have a #[] method (and it’s not clear the data structure is any more
efficient than an array):

require ‘yaml’

h = YAML.load <<EOY
section1: !!omap
- link1: home
- link2: my page
- link3: logout
EOY

p h[“section1”][“link1”] # ==> undef method

Anyone have any enlightenment…?


#6

On Aug 1, 2007, at 11:56 PM, d c wrote:

link1: home
link2: my page
link3: logout

section2:
… etc

http://drawohara.com/post/7519952

enjoy.

a @ http://drawohara.com/


#7

On Aug 1, 10:56 pm, “d c” removed_email_address@domain.invalid wrote:

link3: logout
section:
{ link1, home, link2, mypage … }

on the subject, what do people like as a clear examples site? the spec does
its best to make YAML as unreadable as XML…http://yaml.org/spec/current.html#id2540046

http://yaml4r.sourceforge.net/cookbook/
seems good

thanks!

YAML has a secondary type called an omap. It is supported in the syck
implementation:

section1: !omap

  • link1: home
  • link2: my page
  • link3: logout

The type is YAML::Omap.

T.


#8

On Aug 2, 11:17 am, Joel VanderWerf removed_email_address@domain.invalid wrote:

That still loads as an array though:
p h

Anyone have any enlightenment…?

Syck isn’t 1.1 compliant (AFAIK) so you have a typo in your last
example. It needs to be !omap, not !!omap.

h = YAML::Omap[‘a’,1,‘b’,2]
=> [[“a”, 1], [“b”, 2]]
h[‘a’]
=> 1

T.


#9

Trans wrote:

Syck isn’t 1.1 compliant (AFAIK) so you have a typo in your last
example. It needs to be !omap, not !!omap.

Syck does load !!omap, but the resulting object doesn’t behave very
usefully. I’m not quite sure what it’s supposed to do…


#10

On Aug 2, 11:25 pm, Joel VanderWerf removed_email_address@domain.invalid wrote:

Trans wrote:

Syck isn’t 1.1 compliant (AFAIK) so you have a typo in your last
example. It needs to be !omap, not !!omap.

Syck does load !!omap, but the resulting object doesn’t behave very
usefully. I’m not quite sure what it’s supposed to do…

It’s loading it as an unknown private type.

x = %{
a: !!omap
- x: 1
- y: 2
}
=> “\na: !!omap\n - x: 1\n - y: 2\n”
r = YAML::load(x)
=> {“a”=>#<YAML::PrivateType:0xb79a5058 @type_id=“omap”,
@value=[{“x”=>1}, {“y”=>2}]>}

Which is why it doesn’t know #[], but it knows #value:

r[“a”].value
=> [{“x”=>1}, {“y”=>2}]

T.