Ruby Inserting Key, Value Elements in Hash

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:

  1. Use map to iterate over the elements in list and build a new array at the same time
  2. Since each element is a hash with one item, destruct that into a key and value
  3. 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



Leave a reply



Submit