Access nested hash element specified by an array of keys [duplicate] - ruby

This question already has answers here:
ruby use array tvalues to index nested hash of hash [duplicate]
(4 answers)
Map array of ints to nested array access
(2 answers)
Closed 8 years ago.
I'm trying to get a general solution to the problem of accessing an element in a nested hash given an array of key values,e.g.:
hash = { "a" => { "b" => 'foo' }}
array = ["a", "b"]
function(array)
=> "foo"
I'm guessing this could be a one-liner. It also is quite closely related to this problem:
Ruby convert array to nested hash

hash = { "a" => { "b" => 'foo' }}
array = ["a", "b"]
array.inject(hash,:fetch)
# => "foo"
array.inject(hash,:[])
# => "foo"

Related

RUBY WATIR - Sort duplicate keys stored in Hash [duplicate]

This question already has answers here:
Ruby Hash with duplicate keys?
(2 answers)
Closed 6 years ago.
I am trying sort Hash keys, (Keys can be duplicate) but Ruby is ignoring the duplicate Key and then sorting remaining keys with warning as below.
Code :
gridColumn1= Hash.new{|hsh,key| hsh[key] = [] }
gridColumn1 = { "z"=>["AAPL"], "A"=>["B"], "A"=>["AAPL", "FB", "GE"], "GOOG"=>["HD", "QQQ", "SCHW"], "V"=>[]}
gridColumn1.sort.to_h
Actual Output :
{"A"=>["AAPL", "FB", "GE"], "GOOG"=>["HD", "QQQ", "SCHW"], "V"=>[], "z"=>["AAPL"]}
with warning: duplicated key at line 14 ignored: "A"
I am expecting :
{"A"=>["B"], "A"=>["AAPL", "FB", "GE"], "GOOG"=>["HD", "QQQ", "SCHW"], "V"=>[], "z"=>["AAPL"]}
Ruby hash cannot have duplicate keys, it's whole purpose is to map key -> value.
To have duplicate keys - you can use an array of arrays:
gridColumn1 = [
["z", ["AAPL"]],
["A",["B"]],
["A",["AAPL", "FB", "GE"]],
["GOOG", ["HD", "QQQ", "SCHW"]],
["V", []]
]
gridColumn1.sort_by &:first
# => [["A", ["B"]], ["A", ["AAPL", "FB", "GE"]], ["GOOG", ["HD", "QQQ", "SCHW"]], ["V", []], ["z", ["AAPL"]]]

ruby merge two hash by same key and same values [duplicate]

This question already has answers here:
How to merge Ruby hashes
(4 answers)
Closed 6 years ago.
Note: that the two hashes has the with same key and the same values
a = {:ip=>'192.168.2.1',:b=>2}
b = {:ip=>'192.168.2.1',:c=>4}
i want to merge them to a new hash like this
newhash= {:ip=>'192.168.2.1',:b=>2,:c=4}
Use Hash#merge
a = {:ip=>"192.168.2.1", :b=>2}
b = {:ip=>"192.168.2.1", :c=>4}
newhash = a.merge(b)
#=> {:ip=>"192.168.2.1", :b=>2, :c=>4}

Initializing a Hash with empty array unexpected behaviour [duplicate]

This question already has answers here:
Strange, unexpected behavior (disappearing/changing values) when using Hash default value, e.g. Hash.new([])
(4 answers)
Closed 3 years ago.
I want to initialize a Hash with an empty Array and for every new key push a certain value to that array.
Here's what I tried to do:
a = Hash.new([])
# => {}
a[1] << "asd"
# => ["asd"]
a
# => {}
The expected output for a was {1 => ["asd"]} but that didn't happen. What am I missing here?
Ruby version:
ruby 2.0.0p598 (2014-11-13 revision 48408) [x86_64-linux]
Just do
a = Hash.new { |h, k| h[k] = [] }
a[1] << "asd"
a # => {1=>["asd"]}
Read the below lines from the Hash::new documentation. It really explains why you didn't get the desired result.
new(obj) → new_hash
If obj is specified, this single object will be used for all default values.
new {|hash, key| block } → new_hash
If a block is specified, it will be called with the hash object and the key, and should return the default value. It is the block’s responsibility to store the value in the hash if required.
You can test by hand :
a = Hash.new([])
a[1].object_id # => 2160424560
a[2].object_id # => 2160424560
Now with the above style of Hash object creation, you can see every access to an unknown key, returning back the same default object. Now the other way, I meant block way :
b = Hash.new { |h, k| [] }
b[2].object_id # => 2168989980
b[1].object_id # => 2168933180
So, with the block form, every unknown key access, returning a new Array object.

Whether array consists of any value of another array [duplicate]

This question already has answers here:
How can I check if a Ruby array includes one of several values?
(5 answers)
Closed 8 years ago.
I have an array a = ["1","2","3","6","7"] and another array b = ["2","4","7"]. I want to check if any content of b exists in a or not.
You can do
a = ["1","2","3","6","7"]
b = ["2","4","7"]
b.any? { |e| a.include?(e) }
that is so simple:
(a & b).blank?
actually what does it do is, it takes intersection of two array and returns the result then check if the result is blank/empty.
Use & operator of Ruby, it will return an array with intersection values of two arrays, below is an example.
pry(main)> a = ["1","2","3","6","7"]
=> ["1", "2", "3", "6", "7"]
pry(main)> b = ["2","4","7"]
=> ["2", "4", "7"]
pry(main)> a & b
=> ["2", "7"]
pry(main)> (a & b).empty?
=> false
In Rails, you can also use blank?
pry(main)> (a & b).blank?
=> false
Hope the above example helps

Modifying a hash with multiple occurrences [duplicate]

This question already has answers here:
How do I copy a hash in Ruby?
(13 answers)
Closed 8 years ago.
a is a hash. s is an array where I want to push the hash a iteratively. The idea is to retain the value of each iteratively pushed hash independently. Here is what I tried.
a = {:a=> 1, :b=>2}
s = []
s << a
s << a # => [{:b=>2, :a=>1}, {:b=>2, :a=>1}]
a[:b] = 3
s # => [{:b=>3, :a=>1}, {:b=>3, :a=>1}]
t = []
t.push(a) # => [{:b=>3, :a=>1}]
t.push(a) # => [{:b=>3, :a=>1}, {:b=>3, :a=>1}]
a[:b] = 4
t # => [{:b=>4, :a=>1}, {:b=>4, :a=>1}]
The above doesn't give me the solution: Changing a changes the values in the elements inside the array which were previously pushed. After pushing a to s twice, I changed a[:b] from 2 to 3, and all the elements reflected the change. Suggestion for this please.
Use dup every time you're adding to s
s << a.dup
The dup method will create shallow copy of hash.
Update:
In case if the shallow copy doesn't satisfy the requirements, then use Marshaling
s << Marshal.load( Marshal.dump(a) )
Use
s << Hash[a]
This will copy the Hash and allow you to change the original.

Resources