YANQ: Nesting in YAML

B

basi

Hello,

How does one tell YAML to use an array substructure rather than a hash?
Given the following YAML data:

an:
- at sf
- fc di
- ps:
- na vb
- ex anEx
- ps:
- na no
- ex otherEx
- pr pro
in:
- at sf
- fc lo

YAML gives it the structure: {[{[...]}]}, that is, Hash embeds Array
which embeds another Hash which embeds Array, as below (output
reformatted for clarity).

{"an"=>
[ "at sf",
"fc di",
{"ps"=>
["na vb",
"ex anEx"]},
{"ps"=>
["na no",
"ex otherEx",
"pr pro"]}],
"in"=>
["at sf",
"fc lo"]
}

I feel that the structure below: {[[[...]]]}, that is, hash embeds
array which embeds another array makes it easier to pick off keys and
values than the other structure (though, honestly, I haven't gone that
far yet).

{"an"=>
[ "at sf",
"fc di",
"ps"=>
["na vb",
"ex anEx"]],
"ps"=>
["na no",
"ex otherEx",
"pr pro"]]],
"in"=>
["at sf",
"fc lo"]
}

Thanks for the help.
basi
 
L

lists

Hello,

How does one tell YAML to use an array substructure rather than a
hash?

{"an"=>
[ "at sf",
"fc di",
"ps"=>
["na vb",
"ex anEx"]],
"ps"=>
["na no",
"ex otherEx",
"pr pro"]]],
"in"=>
["at sf",
"fc lo"]
}


YAML::dump() might be helpful:

require 'yaml'

hash = {"an"=>
[ "at sf",
"fc di",
{"ps"=>
["na vb",
"ex anEx"]}],
"ps"=>
["na no",
"ex otherEx",
"pr pro"],
"in"=>
["at sf",
"fc lo"]
}

puts YAML::dump(hash)

That will show you the yaml representation of the 'hash' data
structure (I know my 'hash' is different from what you posted, but
yours didn't parse).

Hope this helps,
Ryan
 
Z

Zach Dennis

lists said:
That will show you the yaml representation of the 'hash' data structure
(I know my 'hash' is different from what you posted, but yours didn't
parse).

It's because in the *wanted* structure, the OP tried to say:

{"an"=>
[ "at sf",
"fc di",
"ps"=>
["na vb",
"ex anEx"]],
# etc...
}

{"an"=>
[ "at sf",
"fc di",
"ps"=>
["na vb",
"ex anEx"] ] }

The OP is treating "ps" has a hash key => value pair inside of an array.
This is why you need "ps" to be inside of another hash.

Zach
 
B

basi

Yes, I screwed up the description of the problem big time. Here's a
better description:

Given the YAML statements:

x:
bb:
- boo
aa:
- 2
- 3
y:
cc:
- see
- sea
aa:
- 5

YAML produces:

{"x"=>{"aa"=>[2, 3], "bb"=>["boo"]}, "y"=>{"aa"=>[5], "cc"=>["see",
"sea"]}}

I think I can handle picking up keys and values here, so I'm happy with
the nesting. But now my problem is how to add extra levels of nesting
to the YAML statements, where "see" has its own substructure, something
like:

x:
bb:
- boo
aa:
- 2
- 3
y:
cc:
- see
sea:
- weed
- sick
aa:
- 5

The above doesn't parse. Gives the message:

ArgumentError: parse error on line 9, col 7: ` sea:
'
from c:/ruby/lib/ruby/1.8/YAML.rb:119:in `load'
from c:/ruby/lib/ruby/1.8/YAML.rb:119:in `load'
from (irb):52
from :0


My apologies for the incorrect OP. And thanks.
basi

value3
 
B

Ben Giddings

I feel that the structure below: {[[[...]]]}, that is, hash embeds
array which embeds another array makes it easier to pick off keys and
values than the other structure (though, honestly, I haven't gone that
far yet).

{"an"=>
[ "at sf",
"fc di",
"ps"=>
["na vb",
"ex anEx"]],
"ps"=>
["na no",
"ex otherEx",
"pr pro"]]],
"in"=>
["at sf",
"fc lo"]
}

This doesn't look like a hash containing an array to me. The "ps" entries
inside look like they're hashes, the key is "ps", the value is an array
containing ["na vb", "ex anEx"]...

In any event, I think if you have value: stuff in YAML, it will decide it's a
hash entry. Array entries start with '-'.

If you don't care about the "ps" keys:

irb(main):004:0> puts ["at sf", "fc di", ["na vb", "ex anEx"],["na no", "ex
otherEx", "pr pro"]].to_yaml
---
- at sf
- fc di
-
- na vb
- ex anEx
-
- na no
- ex otherEx
- pr pro


Ben
 
B

Ben Giddings

I think I can handle picking up keys and values here, so I'm happy with
the nesting. But now my problem is how to add extra levels of nesting
to the YAML statements, where "see" has its own substructure, something
like:

x:
bb:
- boo
aa:
- 2
- 3
y:
cc:
- see
sea:
- weed
- sick
aa:
- 5

irb(main):051:0> h = {"x"=>{"aa"=>[2, 3], "bb"=>["boo"]}, "y"=>{"aa"=>[5],
"cc"=>["see", {"sea" => ["weed", "sick"]}]}}
=> {"x"=>{"bb"=>["boo"], "aa"=>[2, 3]}, "y"=>{"cc"=>["see", {"sea"=>["weed",
"sick"]}], "aa"=>[5]}}
irb(main):052:0> puts h.to_yaml
---
x:
bb:
- boo
aa:
- 2
- 3
y:
cc:
- see
-
sea:
- weed
- sick
aa:
- 5
=> nil

Did you mean "sea" has it's own substructure, i.e. the hash key "cc" points to
an array with two values "see" and another hash containing one entry where
the key is "sea" and the value is an array containing "weed" and "sick".

If that's your goal, you were close, all you needed was the line with the dash
on it before "sea:"

Btw, the way I figured this out was by creating the structure in ruby in IRB,
then calling "puts h.to_yaml". There are lots of braces and brackets to work
through, but the error messages tend to be better.

Ben
 
B

basi

Soon as I posted the correct description above, I tried:

in YAML
x:
bb:
- boo
aa:
- 2
- 3
y:
cc:
- see
- sea:
- weed
- sick
aa:
- 5

and got a result that looks good. (I swear I tried that solution before
and it didn't work!)

{"x"=>
{"aa"=>[2, 3],
"bb"=>["boo"]},
"y"=>
{"aa"=>[5],
"cc"=>["see",
{"sea"=>["weed", "sick"]}]}}

Apologies again and cheers!
basi
 
B

basi

But now I cannot get at the values ["weed", "sick"]

irb(main):056:0> h["y"]["cc"]
=> ["see", {"sea"=>["weed", "sick"]}]
irb(main):057:0> h["y"]["cc"]["sea"]
TypeError: cannot convert String into Integer
from (irb):57:in `[]'
from (irb):57
from :0

I think I'm gonna quit for a while. I feel I'm getting sick. I need
some weed, er, I mean sleep.

Cheers,
Basi
 
J

Jamal Hansen

But now I cannot get at the values ["weed", "sick"]
=20
irb(main):056:0> h["y"]["cc"]
=3D> ["see", {"sea"=3D>["weed", "sick"]}]
irb(main):057:0> h["y"]["cc"]["sea"]
TypeError: cannot convert String into Integer
from (irb):57:in `[]'
from (irb):57
from =03:0

I think h["y"]["cc"][1]["sea"][1] would return "sick" since "sea" is a
key in a hash in an array which contains an array. er.. yeah.

-Jamal
 
B

basi

Jamal,
Yes, that'd work for this example. In my project, I would not know
beforehand what the array index would be. I suppose one could extract
the array index from its value.

But, after a good night's sleep, I found the structure that looks like
will work for me: hash all the way down.

Thanks all,
basi
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top