Append key/value pair to hash with in Ruby
There is merge!
.
h = {}
h.merge!(key: "bar")
# => {:key=>"bar"}
Adding values to array hash ruby at a specific position
We are given three objects.
jsonResponse = {
:json=>{
"reply"=>[
{"person"=>"abc", "roll_no"=>"1234", "location"=>"loc1", "score"=>"1"},
{"person"=>"def", "roll_no"=>"1235", "location"=>"loc2", "score"=>"2"},
{"person"=>"fgh", "roll_no"=>"1236", "location"=>"loc3", "score"=>"3"}
]
},
:status=>200
}
key_value_pair_to_add = { 'new_value'=>'new_result' }
key_to_precede = 'location'
We then modify jsonResponse
as follows.
keys_to_shift = jsonResponse[:json]['reply'][0].keys.
drop_while { |k| k != key_to_precede }
#=> ["location", "score"]
jsonResponse[:json]['reply'].each do |h|
h.update('new_value'=>'new_result')
keys_to_shift.each { |k| h.update(k=>h.delete(k)) }
end
jsonResponse
#=> {
# :json=>{
# "reply"=>[
# {"person"=>"abc", "roll_no"=>"1234", "new_value"=>"new_result",
# "location"=>"loc1", "score"=>"1"},
# {"person"=>"def", "roll_no"=>"1235", "new_value"=>"new_result",
# "location"=>"loc2", "score"=>"2"},
# {"person"=>"fgh", "roll_no"=>"1236", "new_value"=>"new_result",
# "location"=>"loc3", "score"=>"3"}
# ]
# },
# :status=>200
# }
See Hash#update (aka merge!
) and Hash#delete.
h.delete('location')
removes the key-value pair 'location'=>'locX'
from h
and returns locX
, after which
h.update('location'=>'locX')
returns that key-value pair to the end of the hash. This is repeated for each key in keys_to_shift
.
Insert new key value into nested hash in Ruby
You need to construct a new array from your existing:
photos = [{"id": "111","photo": "http://photo.com/111.jpeg"}, {"id": "222", "photo": "http://photo.com/222.jpeg"}]
new_photos = photos.map do |photo|
if photo[:id] == '111'
photo.merge(type: 'Profile')
else
photo
end
end
How to add new item to hash
Create the hash:
hash = {:item1 => 1}
Add a new item to it:
hash[:item2] = 2
Adding new keys to a Array Of Hashes
I would probably:
- Use
map
to iterate over the elements inlist
and build a new array at the same time - Since each element is a hash with one item, destruct that into a key and value
- Build the new hash in the correct format
new_list = list.map do |hash|
# e.g. key = "Mary", value = "Die Hard"
key, value = hash.first
{name: key, film: value}
end
This assumes that each hash in the list will have only one item (as you've shown in your example in the question) - you may want to validate this elsewhere, since this solution would ignore any other items in the hash past the first.
How do I append a key value pair to an existing hash in Ruby?
There are 3 ways:
.merge(other_hash)
Returns a new hash containing the contents of other_hash and the contents of hsh.
hash = { a: 1 }
puts hash.merge({ b: 2, c: 3 }) # => {:a=>1, :b=>2, :c=>3}
.merge!(other_hash)
Adds the contents of other_hash to hsh.
hash = { a: 1 }
puts hash.merge!({ b: 2, c: 3 }) # => {:a=>1, :b=>2, :c=>3}
And most efficient way is to modify existing hash, setting new values directly:
hash = { a: 1 }
hash[:b] = 2
hash[:c] = 3
puts hash # => {:a=>1, :b=>2, :c=>3}
Corresponding Benchmarks for these methods:
user system total real
0.010000 0.000000 0.010000 ( 0.013348)
0.010000 0.000000 0.010000 ( 0.003285)
0.000000 0.000000 0.000000 ( 0.000918)
Ruby Inserting Key, Value elements in Hash
I think this is what you're trying to do
class Dictionary
def initialize()
@data = Hash.new { |hash, key| hash[key] = [] }
end
def [](key)
@data[key]
end
def []=(key,words)
@data[key] += [words].flatten
@data[key].uniq!
end
end
d = Dictionary.new
d['tall'] = %w(long word1 word2)
d['something'] = %w(anything foo bar)
d['more'] = 'yes'
puts d.inspect
#=> #<Dictionary:0x42d33c @data={"tall"=>["long", "word1", "word2"], "something"=>["anything", "foo", "bar"], "more"=>["yes"]}>
puts d['tall'].inspect
#=> ["long", "word1", "word2"]
Edit
Now avoids duplicate values thanks to Array#uniq!
.
d = Dictionary.new
d['foo'] = %w(bar baz bof)
d['foo'] = %w(bar zim) # bar will not be added twice!
puts d.inspect
#<Dictionary:0x42d48c @data={"foo"=>["bar", "baz", "bof", "zim"]}>
Inserting an entry in hash at certain position
I suggest you do the following:
- extract the keys from the hash and find the index of the given key
- add one to the index if the given pair is to be inserted after, rather than before, the given key
- convert the hash to an array
- insert the pair in the array before the computed index (which is after the last pair if the index equals the size of the array)
- convert the resulting array back to a hash
def insert_pair(h, key, pair, proximity=:before)
h.to_a.insert(h.keys.index(key) + (proximity==:after ? 1 : 0), pair.first).to_h
end
h = {"set_filter"=>["0"], "test1"=>["=test1"], "test2"=>["=test2"]}
pair = {"test3"=>["=test3"]}
insert_pair(h, "set_filter", pair, :after)
#=> {"set_filter"=>["0"], "test3"=>["=test3"], "test1"=>["=test1"], "test2"=>["=test2"]}
insert_pair(h, "set_filter", pair)
#=> {"test3"=>["=test3"], "set_filter"=>["0"], "test1"=>["=test1"], "test2"=>["=test2"]}
insert_pair(h, "test2", pair, :after)
#=> {"set_filter"=>["0"], "test1"=>["=test1"], "test2"=>["=test2"], "test3"=>["=test3"]}
I've made :before
the default to be consistent with Array#insert.
Here's an alternative approach that does not convert the hash to an array, modify the array and then convert it back to a hash. Rather, it splits the existing hash into two hashes, slips a single-key hash between them and then merges all three into a single hash.
def insert_pair(h, key, pair, proximity=:before)
keys = h.keys
before_keys =
case proximity
when :before
key==keys.first ? [[], keys] : keys.slice_before { |k| k == key }
when :after
keys.slice_after { |k| k == key }
end.first
h.select { |k,_| before_keys.include? k }.
update(pair).
update(h.reject { |k,_| before_keys.include? k })
end
insert_pair(h, "set_filter", pair, :after)
#=> {"set_filter"=>["0"], "test3"=>["=test3"], "test1"=>["=test1"], "test2"=>["=test2"]}
insert_pair(h, "set_filter", pair)
#=> {"test3"=>["=test3"], "set_filter"=>["0"], "test1"=>["=test1"], "test2"=>["=test2"]}
insert_pair(h, "test2", pair, :after)
#=> {"set_filter"=>["0"], "test1"=>["=test1"], "test2"=>["=test2"], "test3"=>["=test3"]}
How do I add a key/value pair to the beginning of a hash?
Ruby passes objects to methods by value, but the value is the reference to the object, so when you set hash=temp_hash
within the add_hash
method, that change only applies inside the method. The value of hash outside the method is unchanged.
def hash_add(hash, new_key, new_value)
temp_hash = {}
temp_hash[new_key.to_sym] = new_value
temp_hash.merge!(hash)
hash = temp_hash
hash
end
h2 = hash_add(hash, 'one', 1)
hash
=> {:two=>2, :three=>3}
h2
=>{:one=>1, :two=>2, :three=>3}
If you want hash to be updated, you need to replace the contents of hash rather than re-point hash at a new object as you did with the clear and re-adding the values. You can also do it with the replace
method.
def hash_add(hash, new_key, new_value)
temp_hash = {}
temp_hash[new_key.to_sym] = new_value
temp_hash.merge!(hash)
hash.replace temp_hash
end
There are some good diagrams about pass by value in "Is Ruby pass by reference or by value?"
Related Topics
Package Configuration for Libffi Is Not Found in MACos While Installing Travis-Cli
Ruby - Problems with Expect and Pty
Nokogiri Recursively Get All Children
Standalone Ruby -- How to Load Different Environments from Database.Yml
How Write into CSV File Properly
Ruby Syntax: Break Out from 'Each.. Do..' Block
Thin Doesn't Respond to Sigint or Sigterm
Why Does Ruby Use Nil to Name the Null Object
Stub Method Only on The First Call with Rspec
Specify Custom Index Name When Using Add_Reference
Ruby, How to Add a Param to an Url That You Don't Know If It Has Any Other Param Already
How to Return a Fixed Length Binary Representation of an Integer in Ruby
What's the Easiest Way to Send a Message Through Outlook with Ruby
What Do I Need to Do to Get Hash.From_Xml() to Work
Are There "Rules" for Ruby Syntactic Sugar