I am trying to create a hash that looks like this:
{"difficulty"=>{"easy"=>{}, "normal"=>{}, "hard"=>{}}, "terrain"=>{"snow"=>{"sleet"=>{}, "powder"=>{}}, "jungle"=>{}, "city"=>{}}}
From a MongoDB collection which is and enumerable list of hashes that looks like this:
{
"_id" : "globalSettings",
"groups" : [
"difficulty",
"terrain"
],
"parent" : null,
"settings" : {
"maxEnemyCount" : 10,
"maxDamageInflicted" : 45,
"enemyHealthPoints" : 40,
"maxEnemySpeed" : 25,
"maxPlayerSpeed" : 32,
"lightShader" : "diffuse",
"fogDepth" : 12,
"terrainModifier" : 9
}
},
{
"_id" : "difficulty",
"groups" : [
"easy",
"normal",
"hard"
],
"parent" : "globalSettings",
"settings" : {
}
}
{
"_id" : "terrain",
"groups" : [
"snow",
"jungle",
"city"
],
"parent" : "globalSettings",
"settings" : {
}
}
{
"_id" : "snow",
"groups" : [
"sleet",
"powder"
],
"parent" : "terrain",
"settings" : {
"fogDepth" : 4
}
}
{
"_id" : "jungle",
"groups" : [ ],
"parent" : "terrain",
"settings" : {
"terrainModifier" : 6
}
}
{
"_id" : "city",
"groups" : [ ],
"parent" : "terrain",
"settings" : {
"lightShader" : "bumpedDiffuse"
}
}
{
"_id" : "easy",
"groups" : [ ],
"parent" : "difficulty",
"settings" : {
"maxEnemyCount" : 5
}
}
{
"_id" : "normal",
"groups" : [ ],
"parent" : "difficulty",
"settings" : {
}
}
{
"_id" : "hard",
"groups" : [ ],
"parent" : "difficulty",
"settings" : {
"maxEnemyCount" : 20
}
}
{
"_id" : "sleet",
"groups" : [ ],
"parent" : "snow",
"settings" : {
"fogDepth" : 2
}
}
{
"_id" : "powder",
"groups" : [ ],
"parent" : "snow",
"settings" : {
"terrainModifier" : 2
}
}
Every time I try to write the function, I get stuck when setting the parent of the group. How do I recurse, yet keep track of the path of hierarchy?
The closest I've come is with this:
def dbCurse(nodes, parent = nil)
withParent, withoutParent = nodes.partition { |n| n['parent'] == parent }
withParent.map do |node|
newNode={}
newNode[node["_id"]]={}
newNode[node["_id"]].merge(node["_id"] => dbCurse(withoutParent, node['_id']))
end
end
which gives me a crazy mix of arrays and hashes:
{"globalSettings"=>[{"difficulty"=>[{"easy"=>[]}, {"normal"=>[]}, {"hard"=>[]}]}, {"terrain"=>[{"snow"=>[{"sleet"=>[]}, {"powder"=>[]}]}, {"jungle"=>[]}, {"city"=>[]}]}]}
I think the arrays are getting mixed in there from the #map but I'm not sure how to get rid of them to get the clean hash of hashes I show at the top of my question.
Thank you, David
So looking at your sample input, I'm going to make a core assumption:
The order of the hash objects in the input list are somewhat well-defined. Namely, that if the
globalSettings
hash refers to the groupdifficulty
, then the next object in the list with_id == 'difficulty'
andparent == 'globalSettings'
is the correct match.If this is true, then you can write a function that accepts a description of what you're looking for (i.e., the object with
_id == 'difficulty'
andparent == 'globalSettings'
) along with a reference to where you want that data stored, which can then recurse using deeper references.The trick here is that I'm handing the recursive call to
doit
the names of the next objects that I'm looking for from the list (using the current object's group list) and pairing each of those desired names with their parent and a reference to where I want the function to put the found data. Each recursive call todoit
will use deeper and deeper references into the original output hash.