Hi there,
I have a hash with various keys and values that are strings.
If the key exists, the following works: h[“foo”] += “bar”
But if the key does not exist, I get an error.
Is it possible in one statement to cover both the cases where the key
does exist (as above) AND the case where the key does not exist - and in
this situation I’d like the new key and value pair to be created in the
hash.
Any help gratefully received!
Andrew S. писал 09.12.2011 09:58:
does exist (as above) AND the case where the key does not exist - and
in
this situation I’d like the new key and value pair to be created in
the
hash.
Any help gratefully received!
$ irb
ruby-1.9.3-p0 :001 > hash = Hash.new("")
=> {}
ruby-1.9.3-p0 :002 > hash[:a] = “test”
=> “test”
ruby-1.9.3-p0 :003 > hash[:a] += " - one"
=> “test - one”
ruby-1.9.3-p0 :004 > hash[:b] += “nothing - two”
=> “nothing - two”
ruby-1.9.3-p0 :005 > hash
=> {:a=>“test - one”, :b=>“nothing - two”}
On Dec 8, 2011, at 21:58 , Andrew S. wrote:
Hi there,
I have a hash with various keys and values that are strings.
If the key exists, the following works: h[“foo”] += “bar”
That only works if the value at key “foo” responds to +. In this case, I
presume, a String.
But if the key does not exist, I get an error.
You only get an error because nil (the default default value) doesn’t
respond to +.
Is it possible in one statement to cover both the cases where the key
does exist (as above) AND the case where the key does not exist - and in
this situation I’d like the new key and value pair to be created in the
hash.
Assuming you want an empty string as your default value:
h = Hash.new { |h,k| h[k] = "" }
That will initialize your hash ‘h’ with a default value proc that gets
run every time you access a key that isn’t yet a member of h. That proc
is passed the hash (self) and they key. We assign a new empty string at
h[k].
On Fri, Dec 9, 2011 at 12:11 AM, Ryan D.
[email protected]wrote:
But if the key does not exist, I get an error.
$ irb
default object.
Additionally:
hash = Hash.new(“”)
modifying the key doesn’t set the key
hash[:foo] << ‘blah’
hash.keys # => []
it modifies the default
hash.default # => “blah”
hash[:foo] # => “blah”
hash[:bar] # => “blah”
On Fri, Dec 09, 2011 at 02:58:18PM +0900, Andrew S. wrote:
hash.
I guess you could get really ugly with it.
h['foo'] = h['foo'].to_s + 'bar'
On Dec 8, 2011, at 22:03 , Peter Z. wrote:
does exist (as above) AND the case where the key does not exist - and in
ruby-1.9.3-p0 :002 > hash[:a] = “test”
=> “test”
ruby-1.9.3-p0 :003 > hash[:a] += " - one"
=> “test - one”
ruby-1.9.3-p0 :004 > hash[:b] += “nothing - two”
=> “nothing - two”
ruby-1.9.3-p0 :005 > hash
=> {:a=>“test - one”, :b=>“nothing - two”}
This is bad. Very bad.
irb(main):007:0> hash[:d] << “blah”
=> “blah”
irb(main):008:0> hash[:e] += " blah"
=> “blah blah”
irb(main):009:0> hash
=> {:b=>“nothing - two”, :e=>“blah blah”, :c=>“blah”, :a=>“test - one”}
Make sure you use the block form initializer whenever you have a mutable
default object.
On Fri, Dec 9, 2011 at 11:28 AM, Andrew S. [email protected]
wrote:
Hi there,
I have a hash with various keys and values that are strings.
If the key exists, the following works: h[“foo”] += “bar”
–
Posted via http://www.ruby-forum.com/.
You can have something like this to check whether the key is present or
not-
h[“key”] += value if h[“key”]
On Dec 8, 2011, at 23:06, Mayank K. [email protected]
wrote:
You can have something like this to check whether the key is present or
not-
h[“key”] += value if h[“key”]
Values can be false/nil.
On Fri, Dec 9, 2011 at 2:53 PM, Robert K.
[email protected]wrote:
h[“key”] += value if h[“key”]
irb(main):008:0> h[:f] += “bar”
Kind regards
robert
–
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
Thanks for the enlightenment!!! Learned something about hashes today.
On Fri, Dec 9, 2011 at 8:38 AM, Ryan D. [email protected]
wrote:
On Dec 8, 2011, at 23:06, Mayank K. [email protected] wrote:
You can have something like this to check whether the key is present or
not-
h[“key”] += value if h[“key”]
Values can be false/nil.
Also, this is inelegant. Either do this to prevent accidental
modification of the default object:
irb(main):006:0> h = Hash.new(“”.freeze)
=> {}
irb(main):007:0> h[:e] += “foo”
=> “foo”
irb(main):008:0> h[:f] += “bar”
=> “bar”
irb(main):009:0> h
=> {:e=>“foo”, :f=>“bar”}
irb(main):010:0> h[:f] += “foo”
=> “barfoo”
irb(main):011:0> h
=> {:e=>“foo”, :f=>“barfoo”}
Or, what I’d consider better because it is more efficient, use
String#<< to append and not create new instances all the time:
irb(main):012:0> h = Hash.new {|ha,k| h[k] = “”}
=> {}
irb(main):013:0> h[:e] << “foo”
=> “foo”
irb(main):014:0> h[:f] << “bar”
=> “bar”
irb(main):015:0> h
=> {:e=>“foo”, :f=>“bar”}
irb(main):016:0> h[:f] << “foo”
=> “barfoo”
Kind regards
robert
On Fri, Dec 9, 2011 at 11:22 AM, Mayank K.
[email protected] wrote:
Thanks for the enlightenment!!! Learned something about hashes today.
You’re welcome. I just had one spelling error:
irb(main):012:0> h = Hash.new {|ha,k| h[k] = “”}
should have been
irb(main):012:0> h = Hash.new {|ha,k| ha[k] = “”}
It does not make a difference in this case (since ha == h) but the
corrected version is more robust (i.e. if someone reassigns h).
Kind regards
robert
Andrew S. wrote in post #1035841:
Hi there,
I have a hash with various keys and values that are strings.
If the key exists, the following works: h[“foo”] += “bar”
But if the key does not exist, I get an error.
Is it possible in one statement to cover both the cases where the key
does exist (as above) AND the case where the key does not exist - and in
this situation I’d like the new key and value pair to be created in the
hash.
Any help gratefully received!
see if this solves your problem:
=begin
One liner to update an hash of string values:
h[:key] = h.has_key?(:key) ? h[:key] += ‘-New_value’ : ‘First_value’
=end
h = {}
h[:foo] = h.has_key?(:foo) ? h[:foo] += ‘-foo_2nd’ : ‘foo_1st’
h[:bar] = h.has_key?(:bar) ? h[:bar] += ‘-bar_2nd’ : ‘bar_1st’
p 'From empty hash: ’ + h.inspect
h[:foo] = h.has_key?(:foo) ? h[:foo] += ‘-foo_2nd’ : ‘foo_1st’
h[:bar] = h.has_key?(:bar) ? h[:bar] += ‘-bar_2nd’ : ‘bar_1st’
p 'Updated hash…: ’ + h.inspect
exit(0)
=begin
Output:
“From empty hash: {:foo=>“foo_1st”- :bar=>“bar_1st”}”
“Updated hash…: {:foo=>“foo_1st-foo_2nd”-
:bar=>“bar_1st-bar_2nd”}”
=end
HTH gfb
Many thanks to all who replied!