Ordered hashes/ yaml?

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

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

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

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.

···

On Aug 1, 10:56 pm, "d c" <lis...@pikkle.com> wrote:

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!

http://drawohara.com/post/7519952

enjoy.

a @ http://drawohara.com/

···

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

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

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

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

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...?

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Hal Fulton 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.

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

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.

···

On Aug 2, 11:17 am, Joel VanderWerf <vj...@path.berkeley.edu> wrote:

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...?

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...

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

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 = %{
      - 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.

···

On Aug 2, 11:25 pm, Joel VanderWerf <vj...@path.berkeley.edu> wrote:
    a: !!omap