Reputation: 2199
Here's my example:
hash = {"buy"=>"Buy ", "quantity"=>"3 ", "get"=>"Get ", "reward"=>"1 ", "free"=>"Free"}
def stripit(value)
#value.gsub!('B', 'C')
value.gsub!('/\s+/', '')
value
end
newhash = hash.update(hash){|key,value| stripit(value)}
puts newhash.inspect
gsub
works on the value -- the first commented replacement works -- but for some reason it is not removing whitespace.
How can I remove whitespaces from a hash value?
Upvotes: 5
Views: 4738
Reputation: 1
You can also use map
with a bang operator of you want, like this:
hash.values.map! {|value| value.strip!}
Upvotes: 0
Reputation: 110675
You do not need the line value
in stripit
if you replace v.gsub!(/\s+/, '')
(or just /\s/
) with v.gsub(/\s/, '')
. That's permitted (and preferred, imo, for better readability and saving a line of code), because Hash#update (aka merge!
) is handling the in-place replacement. (Readers: the asker has that line value
because String#gsub! returns nil
when no change is made.
You may want confirm the hash value is a string before attempting the substitution (unless you are certain that, even in future, there will never be a value that is not a string, but even then, it does no harm to check).
I suggest the following.
hash = {"buy"=>"Buy It ", "quantity"=>"3 ", "get"=>"Get ", "reward"=>"1 ",
"free"=>"Free", "THE answer"=> 42 }
if hash
is not to be mutated:
hash.merge(hash) { |_,v,_| v.is_a?(String) ? v.gsub(/\s/, '') : v }
#=> {"buy"=>"BuyIt", "quantity"=>"3", "get"=>"Get", "reward"=>"1", "free"=>"Free"}
hash
#=> {"buy"=>"Buy It ", "quantity"=>"3 ", "get"=>"Get ", "reward"=>"1 ",
# "free"=>"Free", "THE answer"=>42}
if hash
is to be mutated:
hash.update(hash) { |_,v,_| v.is_a?(String) ? v.gsub(/\s/, '') : v }
#=> {"buy"=>"BuyIt", "quantity"=>"3", "get"=>"Get", "reward"=>"1",
# "free"=>"Free", "THE answer"=>42}
hash
#=> {"buy"=>"BuyIt", "quantity"=>"3", "get"=>"Get", "reward"=>"1",
# "free"=>"Free", "THE answer"=>42}
This uses the forms of Hash#merge and Hash#update
that employ a block to determine the values of keys that are present in both hashes being merged. Here that is of course all keys. See the docs for details, particularly the meanings of the three block variables. (I've represented two of the three block variables with underscores to indicate they are not used in the block calculation.)
Another way
If hash
is not to be mutated:
hash.keys.each_with_object({}) do |k,h|
v = hash[k]
h[k] = v.is_a?(String) ? v.gsub(/\s/, '') : v
end
#=> {"buy"=>"BuyIt", "quantity"=>"3", "get"=>"Get", "reward"=>"1",
# "free"=>"Free", "THE answer"=>42}
hash
#=> {"buy"=>"Buy It ", "quantity"=>"3 ", "get"=>"Get ", "reward"=>"1 ",
# "free"=>"Free", "THE answer"=>42}
If hash
is to be mutated:
hash.keys.each do |k|
v = hash[k]
hash[k] = v.is_a?(String) ? v.gsub(/\s/, '') : v
end
#=> ["buy", "quantity", "get", "reward", "free", "THE answer"]
hash
#=> {"buy"=>"BuyIt", "quantity"=>"3", "get"=>"Get", "reward"=>"1",
# "free"=>"Free", "THE answer"=>42}
Note that in this last case hash
is mutated but the block does not return the updated hash
.
Upvotes: 0
Reputation: 427
I think the problem is that you've wrapped your regex in quotation marks, so it's not matching the way you expect!
value.gsub!(/\s+/, '')
(Edit: complete code, copies original question's code but alters the gsub! argument. Tested with ruby 2.3.1)
hash = {"buy"=>"Buy ", "quantity"=>"3 ", "get"=>"Get ", "reward"=>"1 ", "free"=>"Free"}
def stripit(value)
value.gsub!(/\s+/, '')
value
end
newhash = hash.update(hash){|key,value| stripit(value)}
puts newhash.inspect
Output:
{"buy"=>"Buy", "quantity"=>"3", "get"=>"Get", "reward"=>"1", "free"=>"Free"}
Upvotes: 5
Reputation: 54223
If you want to get a new_hash and not modify the original one :
new_hash = hash.map{|k,v| [k,v.gsub(/\s+/,'')]}.to_h
With Rails or ActiveSupport extensions, it becomes even shorter:
hash.transform_values{|v| v.gsub(/\s+/,'')}
NOTE: It removes any whitespace in the values. "Get A "
will be converted to "GetA"
. String#strip
would just convert it to "Get A"
Upvotes: 1
Reputation: 2869
You can use each
method with strip!
to modify hash values.
hash = {"buy"=>"Buy ", "quantity"=>"3 ", "get"=>"Get ", "reward"=>"1 ", "free"=>"Free"}
hash.each_value(&:strip!)
p hash
# => {"buy"=>"Buy", "quantity"=>"3", "get"=>"Get", "reward"=>"1", "free"=>"Free"}
Upvotes: 12