Structuring ruby multidimensional hash by first hash - ruby

I have the hash below:
mm = {
0 => {
0 => 'p1',
1 => 'p2',
2 => 'p3'
},
1 => {
0 => 'idfp1',
1 => 'idfp2',
2 => 'idfp3'
},
2 => {
0 => 'idfp12',
1 => 'idfp22',
2 => 'idfp32'
}
}
And i'm trying to sort it by the hash with a key of 0. In the first hash (0), there are k-v pairs of number to identifier.
In every subsequent hash (1 and 2), 0 points to the 0 from the first hash, 1 points to the 1 from the first hash, etc.
In each hash after 0 (1 and 2), there are IDs (id for person 1) that belong to p1 (person 1).
I've tried to sort this by creating a new hash with only the first hash in the one above to no avail. This is my attempt. The keys are correct but it's pointing to nil, when it should be pointing to the hash with each person's id.
ids = {}
org = {}
mm[0].each do |id, name|
ids[id] = name
end
mm.drop(1).each do |one|
one.each do |key, id|
org[ids[key]] = id
end
end
How can I achieve this in Ruby?
Edit:
In case the explanation doesn't suffice, here is the desired result:
org = {
'p1' => {
0 => 'idfp1',
1 => 'idfp12'
},
'p2' => {
0 => 'idfp2',
1 => 'idfp22'
},
'p3' => {
0 => 'idfp3',
1 => 'idfp32'
}
}

Two ways:
#1
Code
mm[0].invert.each_with_object({}) { |(k,i),h|
h[k] = (1...mm.size).each_with_object ({}) { |j,g| g[j] = mm[j][i] } }
#=> {"p1"=>{1=>"idfp1", 2=>"idfp12"},
# "p2"=>{1=>"idfp2", 2=>"idfp22"},
# "p3"=>{1=>"idfp3", 2=>"idfp32"}}
Explanation
a = mm[0]
#=> {0=>"p1", 1=>"p2", 2=>"p3"}
b = a.invert
#=> {"p1"=>0, "p2"=>1, "p3"=>2}
b.each_with_object({}) { |(k,i),h|
h[k] = (1...mm.size).each_with_object ({}) { |j,g| g[j] = mm[j][i] } }
#=> {"p1"=>{1=>"idfp1", 2=>"idfp12"},
# "p2"=>{1=>"idfp2", 2=>"idfp22"},
# "p3"=>{1=>"idfp3", 2=>"idfp32"}}
#2
Code
mm.values
.map(&:values)
.transpose
.each_with_object({}) { |a,h| h[a.shift] = Hash[[*(0...a.size)].zip(a) ] }
#=> {"p1"=>{0=>"idfp1", 1=>"idfp12"},
# "p2"=>{0=>"idfp2", 1=>"idfp22"},
# "p3"=>{0=>"idfp3", 1=>"idfp32"}}
Explanation
a = mm.values
#=> [{0=>"p1", 1=>"p2", 2=>"p3" },
# {0=>"idfp1", 1=>"idfp2", 2=>"idfp3" },
# {0=>"idfp12", 1=>"idfp22", 2=>"idfp32"}]
b = a.map(&:values
#=> [[ "p1", "p2", "p3" ],
# [ "idfp1", "idfp2", "idfp3" ],
# [ "idfp12", "idfp22", "idfp32"]]
c = b.transpose
#=> [["p1", "idfp1", "idfp12"],
# ["p2", "idfp2", "idfp22"],
# ["p3", "idfp3", "idfp32"]]
c.each_with_object({}) { |a,h| h[a.shift] = Hash[[*(0...a.size)].zip(a) ] }
#=> {"p1"=>{0=>"idfp1", 1=>"idfp12"},
# "p2"=>{0=>"idfp2", 1=>"idfp22"},
# "p3"=>{0=>"idfp3", 1=>"idfp32"}}

Related

Transform array of nested Hashes into flat array of non-nested hashes

I want to transform the given array into result array:
given = [{
"foo_v1_4" => [{
"derivate_version" => 0,
"layers" => {
"tlayer" => {
"baz" => {
"three" => 0.65
},
"bazbar" => {
"three" => 0.65
}
}
}
}]
}]
# the value of key :one is first hash key (foo_v1_4) plus underscore (_) plus derivate_version (0)
result = [{
one: 'foo_v1_4_0',
tlayer: 'baz',
three: '0.6'
},
{
one: 'foo_v1_4_0',
tlayer: 'bazbar',
three: '0.6'
}
]
What I tried:
given.each do |el |
el.each do |derivat |
derivat.each do |d |
d.each do |layer |
layer.each do |l |
derivat = "#{d}_#{l['derivate_version']}"
puts derivat
end
end
end
end
end
I'm struggling at iterating through "layers" hash, the amount of elements in layers is equal to the amount of elements in result array.
It helps to format the objects so we can better see their structures:
given = [
{
"foo_v1_4" => [
{ "derivate_version" => 0,
"layers" => {
"tlayer" => {
"baz" => { "three" => 0.65 },
"bazbar" => { "three" => 0.65 }
}
}
}
]
}
]
result = [
{
one: 'foo_v1_4_0',
tlayer: 'baz',
three: '0.6'
},
{
one: 'foo_v1_4_0',
tlayer: 'bazbar',
three: '0.6'
}
]
We can begin by writing the structure of result:
result = [
{
one:
tlayer:
three:
},
{
one:
tlayer:
three:
}
]
We see that
given = [ { "foo_v1_4" => <array> } ]
The values of the keys :one in the hash result[0] is therefore the first key of the first element of given:
one_val = given[0].keys[0]
#=> "foo_v1_4"
result = [
{
one: one_val
tlayer:
three:
},
{
one: one_val
tlayer:
three:
}
]
All the remaining objects of interest are contained in the hash
h = given[0]["foo_v1_4"][0]["layers"]["layer"]
#=> {
# "baz"=>{ "three"=>0.65 },
# "bazbar"=>{ "three"=>0.65 }
# }
so it is convenient to define it. We see that:
h.keys[0]
#=> "baz"
h.keys[1]
#=> "bazaar"
h["bazbar"]["three"]
#=> 0.65
Note that it generally is not good practice to assume that hash keys are ordered in a particular way.
We may now complete the construction of result,
v = h["bazbar"]["three"].truncate(1)
#=> 0.6
result = [
{
one: one_val,
tlayer: h.keys[0],
three: v
},
{ one: one_val,
tlayer: h.keys[1],
three: v
}
]
#=> [
# { :one=>"foo_v1_4", :tlayer=>"baz", :three=>0.6 },
# { :one=>"foo_v1_4", :tlayer=>"bazbar", :three=>0.6 }
# ]
The creation of the temporary objects one_val, h, and v improves time- and space-efficiency, makes the calculations easier to test and improves the readability of the code.
Try the below:
result = []
given.each do |level1|
level1.each do |key, derivate_versions|
derivate_versions.each do |layers|
# iterate over the elements under tlayer
layers.dig('layers', 'tlayer').each do |tlayer_key, tlayer_value|
sub_result = {}
# key - foo_v1_4, layers['derivate_version'] - 0 => 'foo_v1_4_0'
sub_result[:one] = key + '_' + layers['derivate_version'].to_s
# talyer_key - baz, barbaz
sub_result[:tlayer] = tlayer_key
# talyer_value - { "three" => 0.65 }
sub_result[:three] = tlayer_value['three']
result << sub_result
end
end
end
end
The value of result will be:
2.6.3 :084 > p result
[{:one=>"foo_v1_4_0", :tlayer=>"baz", :three=>0.65}, {:one=>"foo_v1_4_0", :tlayer=>"bazbar", :three=>0.65}]

How to find the largest value of a hash in an array of hashes

In my array, I'm trying to retrieve the key with the largest value of "value_2", so in this case, "B":
myArray = [
"A" => {
"value_1" => 30,
"value_2" => 240
},
"B" => {
"value_1" => 40,
"value_2" => 250
},
"C" => {
"value_1" => 18,
"value_2" => 60
}
]
myArray.each do |array_hash|
array_hash.each do |key, value|
if value["value_2"] == array_hash.values.max
puts key
end
end
end
I get the error:
"comparison of Hash with Hash failed (ArgumentError)".
What am I missing?
Though equivalent, the array given in the question is generally written:
arr = [{ "A" => { "value_1" => 30, "value_2" => 240 } },
{ "B" => { "value_1" => 40, "value_2" => 250 } },
{ "C" => { "value_1" => 18, "value_2" => 60 } }]
We can find the desired key as follows:
arr.max_by { |h| h.values.first["value_2"] }.keys.first
#=> "B"
See Enumerable#max_by. The steps are:
g = arr.max_by { |h| h.values.first["value_2"] }
#=> {"B"=>{"value_1"=>40, "value_2"=>250}}
a = g.keys
#=> ["B"]
a.first
#=> "B"
In calculating g, for
h = arr[0]
#=> {"A"=>{"value_1"=>30, "value_2"=>240}}
the block calculation is
a = h.values
#=> [{"value_1"=>30, "value_2"=>240}]
b = a.first
#=> {"value_1"=>30, "value_2"=>240}
b["value_2"]
#=> 240
Suppose now arr is as follows:
arr << { "D" => { "value_1" => 23, "value_2" => 250 } }
#=> [{"A"=>{"value_1"=>30, "value_2"=>240}},
# {"B"=>{"value_1"=>40, "value_2"=>250}},
# {"C"=>{"value_1"=>18, "value_2"=>60}},
# {"D"=>{"value_1"=>23, "value_2"=>250}}]
and we wish to return an array of all keys for which the value of "value_2" is maximum (["B", "D"]). We can obtain that as follows.
max_val = arr.map { |h| h.values.first["value_2"] }.max
#=> 250
arr.select { |h| h.values.first["value_2"] == max_val }.flat_map(&:keys)
#=> ["B", "D"]
flat_map(&:keys) is shorthand for:
flat_map { |h| h.keys }
which returns the same array as:
map { |h| h.keys.first }
See Enumerable#flat_map.
Code
p myArray.pop.max_by{|k,v|v["value_2"]}.first
Output
"B"
I'd use:
my_array = [
"A" => {
"value_1" => 30,
"value_2" => 240
},
"B" => {
"value_1" => 40,
"value_2" => 250
},
"C" => {
"value_1" => 18,
"value_2" => 60
}
]
h = Hash[*my_array]
# => {"A"=>{"value_1"=>30, "value_2"=>240},
# "B"=>{"value_1"=>40, "value_2"=>250},
# "C"=>{"value_1"=>18, "value_2"=>60}}
k = h.max_by { |k, v| v['value_2'] }.first # => "B"
Hash[*my_array] takes the array of hashes and turns it into a single hash. Then max_by will iterate each key/value pair, returning an array containing the key value "B" and the sub-hash, making it easy to grab the key using first:
k = h.max_by { |k, v| v['value_2'] } # => ["B", {"value_1"=>40, "value_2"=>250}]
I guess the idea of your solution is looping through each hash element and compare the found minimum value with hash["value_2"].
But you are getting an error at
if value["value_2"] == array_hash.values.max
Because the array_hash.values is still a hash
{"A"=>{"value_1"=>30, "value_2"=>240}}.values.max
#=> {"value_1"=>30, "value_2"=>240}
It should be like this:
max = nil
max_key = ""
myArray.each do |array_hash|
array_hash.each do |key, value|
if max.nil? || value.values.max > max
max = value.values.max
max_key = key
end
end
end
# max_key #=> "B"
Another solution:
myArray.map{ |h| h.transform_values{ |v| v["value_2"] } }.max_by{ |k| k.values }.keys.first
You asked "What am I missing?".
I think you are missing a proper understanding of the data structures that you are using. I suggest that you try printing the data structures and take a careful look at the results.
The simplest way is p myArray which gives:
[{"A"=>{"value_1"=>30, "value_2"=>240}, "B"=>{"value_1"=>40, "value_2"=>250}, "C"=>{"value_1"=>18, "value_2"=>60}}]
You can get prettier results using pp:
require 'pp'
pp myArray
yields:
[{"A"=>{"value_1"=>30, "value_2"=>240},
"B"=>{"value_1"=>40, "value_2"=>250},
"C"=>{"value_1"=>18, "value_2"=>60}}]
This helps you to see that myArray has only one element, a Hash.
You could also look at the expression array_hash.values.max inside the loop:
myArray.each do |array_hash|
p array_hash.values
end
gives:
[{"value_1"=>30, "value_2"=>240}, {"value_1"=>40, "value_2"=>250}, {"value_1"=>18, "value_2"=>60}]
Not what you expected? :-)
Given this, what would you expect to be returned by array_hash.values.max in the above loop?
Use p and/or pp liberally in your ruby code to help understand what's going on.

Convert array into hash and add a counter value to the new hash

I have the following array of hashes:
[
{"BREAD" => {:price => 1.50, :discount => true }},
{"BREAD" => {:price => 1.50, :discount => true }},
{"MARMITE" => {:price => 1.60, :discount => false}}
]
And I would like to translate this array into a hash that includes the counts for each item:
Output:
{
"BREAD" => {:price => 1.50, :discount => true, :count => 2},
"MARMITE" => {:price => 1.60, :discount => false, :count => 1}
}
I have tried two approaches to translate the array into a hash.
new_cart = cart.inject(:merge)
hash = Hash[cart.collect { |item| [item, ""] } ]
Both work but then I am stumped at how to capture and pass the count value.
Expected output
{
"BREAD" => {:price => 1.50, :discount => true, :count => 2},
"MARMITE" => {:price => 1.60, :discount => false, :count => 1}
}
We are given the array:
arr = [
{"BREAD" => {:price => 1.50, :discount => true }},
{"BREAD" => {:price => 1.50, :discount => true }},
{"MARMITE" => {:price => 1.60, :discount => false}}
]
and make the assumption that each hash has a single key and if two hashes have the same (single) key, the value of that key is the same in both hashes.
The first step is create an empty hash to which will add key-value pairs:
h = {}
Now we loop through arr to build the hash h. I've added a puts statement to display intermediate values in the calculation.
arr.each do |g|
k, v = g.first
puts "k=#{k}, v=#{v}"
if h.key?(k)
h[k][:count] += 1
else
h[k] = v.merge({ :count => 1 })
end
end
displays:
k=BREAD, v={:price=>1.5, :discount=>true}
k=BREAD, v={:price=>1.5, :discount=>true}
k=MARMITE, v={:price=>1.6, :discount=>false}
and returns:
#=> [{"BREAD" =>{:price=>1.5, :discount=>true}},
# {"BREAD" =>{:price=>1.5, :discount=>true}},
# {"MARMITE"=>{:price=>1.6, :discount=>false}}]
each always returns its receiver (here arr), which is not what we want.
h #=> {"BREAD"=>{:price=>1.5, :discount=>true, :count=>2},
# "MARMITE"=>{:price=>1.6, :discount=>false, :count=>1}}
is the result we need. See Hash#key? (aka, has_key?), Hash#[], Hash#[]= and Hash#merge.
Now let's wrap this in a method.
def hashify(arr)
h = {}
arr.each do |g|
k, v = g.first
if h.key?(k)
h[k][:count] += 1
else
h[k] = v.merge({ :count=>1 })
end
end
h
end
hashify(arr)
#=> {"BREAD"=>{:price=>1.5, :discount=>true, :count=>2},
# "MARMITE"=>{:price=>1.6, :discount=>false, :count=>1}}
Rubyists would often use the method Enumerable#each_with_object to simplify.
def hashify(arr)
arr.each_with_object({}) do |g,h|
k, v = g.first
if h.key?(k)
h[k][:count] += 1
else
h[k] = v.merge({ :count => 1 })
end
end
end
Compare the two methods to identify their differences. See Enumerable#each_with_object.
When, as here, the keys are symbols, Ruby allows you to use the shorthand { count: 1 } for { :count=>1 }. Moreover, she permits you to write :count = 1 or count: 1 without the braces when the hash is an argument. For example,
{}.merge('cat'=>'meow', dog:'woof', :pig=>'oink')
#=> {"cat"=>"meow", :dog=>"woof", :pig=>"oink"}
It's probably more common to see the form count: 1 when keys are symbols and for the braces to be omitted when a hash is an argument.
Here's a further refinement you might see. First create
h = arr.group_by { |h| h.keys.first }
#=> {"BREAD" =>[{"BREAD"=>{:price=>1.5, :discount=>true}},
# {"BREAD"=>{:price=>1.5, :discount=>true}}],
# "MARMITE"=>[{"MARMITE"=>{:price=>1.6, :discount=>false}}]}
See Enumerable#group_by. Now convert the values (arrays) to their sizes:
counts = h.transform_values { |arr| arr.size }
#=> {"BREAD"=>2, "MARMITE"=>1}
which can be written in abbreviated form:
counts = h.transform_values(&:size)
#=> {"BREAD"=>2, "MARMITE"=>1}
See Hash#transform_values. We can now write:
uniq_arr = arr.uniq
#=> [{"BREAD"=>{:price=>1.5, :discount=>true}},
#= {"MARMITE"=>{:price=>1.6, :discount=>false}}]
uniq_arr.each_with_object({}) do |g,h|
puts "g=#{g}"
k,v = g.first
puts " k=#{k}, v=#{v}"
h[k] = v.merge(counts: counts[k])
puts " h=#{h}"
end
which displays:
g={"BREAD"=>{:price=>1.5, :discount=>true}}
k=BREAD, v={:price=>1.5, :discount=>true}
h={"BREAD"=>{:price=>1.5, :discount=>true, :counts=>2}}
g={"MARMITE"=>{:price=>1.6, :discount=>false}}
k=MARMITE, v={:price=>1.6, :discount=>false}
h={"BREAD"=>{:price=>1.5, :discount=>true, :counts=>2},
"MARMITE"=>{:price=>1.6, :discount=>false, :counts=>1}}
and returns:
#=> {"BREAD"=>{:price=>1.5, :discount=>true, :counts=>2},
# "MARMITE"=>{:price=>1.6, :discount=>false, :counts=>1}}
See Array#uniq.
This did the trick:
arr = [
{ bread: { price: 1.50, discount: true } },
{ bread: { price: 1.50, discount: true } },
{ marmite: { price: 1.60, discount: false } }
]
Get the count for each occurrence of hash, add as key value pair and store:
h = arr.uniq.each { |x| x[x.first.first][:count] = arr.count(x) }
Then convert hashes into arrays, flatten to a single array then construct a hash:
Hash[*h.collect(&:to_a).flatten]
#=> {:bread=>{:price=>1.50, :discount=>true, :count=>2}, :marmite=>{:price=>1.60, :discount=>false, :count=>1}}
Combined a couple of nice ideas from here:
https://raycodingdotnet.wordpress.com/2013/08/05/array-of-hashes-into-single-hash-in-ruby/
and here:
http://carol-nichols.com/2015/08/07/ruby-occurrence-couting/

print out Hash key and value pairs recursively

I am trying to define a function that it can print out any hash values in a tree format. The function will do something like this:
From
{"parent1"=>
{"child1" => { "grandchild1" => 1,
"grandchild2" => 2},
"child2" => { "grandchild3" => 3,
"grandchild4" => 4}}
}
To
parent1:
child1:
grandchild1:1
grandchild2:2
child2:
grandchild3:3
grandchild4:4
And this is my code so far:
def readprop(foo)
level = ''
if foo.is_a?(Hash)
foo.each_key {|key| if foo[key].nil? == false
puts level + key + ":"
level += " "
readprop(foo[key])
end
}
else
puts level + foo
level = level[0,level.length - 2]
end
end
and it will give me a bad format like this:
parent1:
child1:
grandchild1:
1
grandchild2:
2
child2:
grandchild3:
3
grandchild4:
4
You are almost there. One way to solve it is to make level a part of the recursive function parameters. x is the hash in the question.
Simple recursive version:
def print_hash(h,spaces=4,level=0)
h.each do |key,val|
format = "#{' '*spaces*level}#{key}: "
if val.is_a? Hash
puts format
print_hash(val,spaces,level+1)
else
puts format + val.to_s
end
end
end
print_hash(x)
#parent1:
# child1:
# grandchild1: 1
# grandchild2: 2
# child2:
# grandchild3: 3
# grandchild4: 4
In this case you could also convert it to YAML (as mentioned in a comment above)
require 'YAML'
puts x.to_yaml
#---
#parent1:
# child1:
# grandchild1: 1
# grandchild2: 2
# child2:
# grandchild3: 3
# grandchild4: 4
I would use recursion, but there is another way that might be of interest to some. Below I've used a "pretty printer", awesome-print, to do part of the formatting (the indentation in particular), saving the result to a string, and then applied a couple of gsub's to the string to massage the results into the desired format.
Suppose your hash were as follows:
h = { "parent1"=>
{ "child1" => { "grandchild11" => 1,
"grandchild12" => { "great grandchild121" => 3 } },
"child2" => { "grandchild21" => { "great grandchild211" =>
{ "great great grandchild2111" => 4 } },
"grandchild22" => 2 }
}
}
We could then do the following.
require 'awesome_print'
puts str = h.awesome_inspect(indent: -5, index: false, plain: true).
gsub(/^\s*(?:{|},?)\s*\n|[\"{}]/, '').
gsub(/\s*=>\s/, ':')
prints
parent1:
child1:
grandchild11:1,
grandchild12:
great grandchild121:3
child2:
grandchild21:
great grandchild211:
great great grandchild2111:4
grandchild22:2
The steps:
str = h.awesome_inspect(indent: -5, index: false, plain: true)
puts str prints
{
"parent1" => {
"child1" => {
"grandchild11" => 1,
"grandchild12" => {
"great grandchild121" => 3
}
},
"child2" => {
"grandchild21" => {
"great grandchild211" => {
"great great grandchild2111" => 4
}
},
"grandchild22" => 2
}
}
}
s1 = str.gsub(/^\s*(?:{|},?)\s*\n|[\"{}]/, '')
puts s1 prints
parent1 =>
child1 =>
grandchild11 => 1,
grandchild12 =>
great grandchild121 => 3
child2 =>
grandchild21 =>
great grandchild211 =>
great great grandchild2111 => 4
grandchild22 => 2
s2 = s1.gsub(/\s*=>\s/, ':')
puts s2 prints the result above.
Not exactly what you require but I will submit this answer as I think you may find it useful:
require 'yaml'
hash = {"parent1"=> {"child1" => { "grandchild1" => 1,"grandchild2" => 2},
"child2" => { "grandchild3" => 3,"grandchild4" => 4}}}
puts hash.to_yaml
prints:
---
parent1:
child1:
grandchild1: 1
grandchild2: 2
child2:
grandchild3: 3
grandchild4: 4
See Ruby Recursive Tree
Suppose we have
#$ mkdir -p foo/bar
#$ mkdir -p baz/boo/bee
#$ mkdir -p baz/goo
We can get
{
"baz"=>{
"boo"=>{
"bee"=>{}},
"goo"=>{}},
"foo"=>{
"bar"=>{}}}
We can traverse the tree as the following. So, here's a way to make a Hash based on directory tree on disk:
Dir.glob('**/*'). # get all files below current dir
select{|f|
File.directory?(f) # only directories we need
}.map{|path|
path.split '/' # split to parts
}.inject({}){|acc, path| # start with empty hash
path.inject(acc) do |acc2,dir| # for each path part, create a child of current node
acc2[dir] ||= {} # and pass it as new current node
end
acc
}
Thanks to Mladen Jablanović in the other answer for this concept.

How to insert a hash inside a hash ruby

I was wondering how I could insert a hash into another hash. For example, in:
{"abcd"=>{}, "hgfe"=>34567}
I want to put "hgfe" => 34567 into the "abcd" key.
output:
{"abcd"=>{"hgfe" => 34567}}
im wanting to convert this hash
"##### RUBY HASH ####
(1)
INPUT
{
'abcd.hgfe' => 34567,
'abcd.efgh.hijk' => 12345,
'abcd.efgh.ijkl' => 56789,
'wxyz.abcd' => 9876,
'wxyz.uvwx.abcd' => 23456,
}
(1)
OUTPUT
{
'abcd' => {
'efgh' => {
'hijk' => 12345,
'ijkl' => 56789
},
'hgfe' => 34567,
},
'wxyz' => {
'abcd' => 9876,
'uvwx' => {'abcd' => 23456}
}
}
"
my currrent code:
def method1(hash)
result = {}
array2 = []
hash.each_pair do|k, v|
array1 = k.split('.')
count = array1.length
hash2 = {}
array1.each_with_index do |str, index|
if (index + 1) == count
hash2[str] = v
else
hash2[str] = {}
end
end
puts hash2.inspect
puts "--------------"
end
result
end
hash_result = method1(h2c)
Do as below
hash = {"abcd"=>{}, "hgfe"=>34567}
hash['abcd']['hgfe'] = hash.delete('hgfe')
hash # => {"abcd"=>{"hgfe"=>34567}}
You can write something like below :
def delete_key_and_add_to_another_key(hash, update_key, del_key)
hash[update_key][del_key] = hash.delete(del_key)
hash
end
hash = {"abcd"=>{}, "hgfe"=>34567}
delete_key_and_add_to_another_key(hash, 'abcd', 'hgfe')
h = {"abcd"=>{}, "hgfe"=>34567}
f, l = h.partition { |_,v| v =={} }.flatten(1)
{ f.first=> { l.first => l.last } }
#=> {"abcd"=>{"hgfe"=>34567}}

Resources