Ruby Use Array Tvalues to Index Nested Hash of Hash

ruby use array tvalues to index nested hash of hash

And then there's:

keys.inject(hash, :fetch)

or for earlier Ruby versions:

keys.inject(hash) {|h, k| h[k]}

If you did want to use recursion, a more Rubyesque approach would be:

def get_value(obj, keys)
keys.empty? ? obj : get_value(obj[keys[0]], keys[1..-1])
end

Access nested hash element specified by an array of keys

hash = { "a" => { "b" => 'foo' }}
array = ["a", "b"]

array.inject(hash,:fetch)
# => "foo"
array.inject(hash,:[])
# => "foo"

change value in hash using an array of keys in ruby

Use all but the last key to get the most deeply nested Hash, then assign normally using the last key.

keys[0...-1].inject(hash, :fetch)[keys.last] = value

Ruby doesn't have references so you can't reassign the value directly. Instead you have to reassign the object pointer, which means going up one level of nesting.

What is the most ruby-ish way of accessing nested hash values at arbitrary depths?

def val_for(hash, keys)
keys.reduce(hash) { |h, key| h[key] }
end

This will raise an exception if some intermediate key is not found. Note also that this is completely equivalent to keys.reduce(hash, :[]), but this may very well confuse some readers, I'd use the block.

How to avoid NoMethodError for missing elements in nested hashes, without repeated nil checks?

Ruby 2.3.0 introduced a new method called dig on both Hash and Array that solves this problem entirely.

name = params.dig(:company, :owner, :name)

It returns nil if the key is missing at any level.

If you are using a version of Ruby older than 2.3, you can use the ruby_dig gem or implement it yourself:

module RubyDig
def dig(key, *rest)
if value = (self[key] rescue nil)
if rest.empty?
value
elsif value.respond_to?(:dig)
value.dig(*rest)
end
end
end
end

if RUBY_VERSION < '2.3'
Array.send(:include, RubyDig)
Hash.send(:include, RubyDig)
end

How to efficiently build a tree from a flat structure?

Store IDs of the objects in a hash table mapping to the specific object. Enumerate through all the objects and find their parent if it exists and update its parent pointer accordingly.

class MyObject
{ // The actual object
public int ParentID { get; set; }
public int ID { get; set; }
}

class Node
{
public List<Node> Children = new List<Node>();
public Node Parent { get; set; }
public MyObject AssociatedObject { get; set; }
}

IEnumerable<Node> BuildTreeAndGetRoots(List<MyObject> actualObjects)
{
Dictionary<int, Node> lookup = new Dictionary<int, Node>();
actualObjects.ForEach(x => lookup.Add(x.ID, new Node { AssociatedObject = x }));
foreach (var item in lookup.Values) {
Node proposedParent;
if (lookup.TryGetValue(item.AssociatedObject.ParentID, out proposedParent)) {
item.Parent = proposedParent;
proposedParent.Children.Add(item);
}
}
return lookup.Values.Where(x => x.Parent == null);
}


Related Topics



Leave a reply



Submit