Forum: Ruby replace values in hash

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A74096209c78118ff69d50a51129d697?d=identicon&s=25 Jason Lillywhite (jlillywh)
on 2008-11-05 07:55
how would I iterate over a hash, such as

x = { 'a' => "hi", 'b' => nil, 'c' => "do"}

and replace nil values with 'foo' then return the hash again?
45196398e9685000d195ec626d477f0e?d=identicon&s=25 Thomas Sawyer (7rans)
on 2008-11-05 08:41
(Received via mailing list)
On Nov 5, 1:53 am, Jason Lillywhite <jason.lillywh...@gmail.com>
wrote:
> how would I iterate over a hash, such as
>
> x = { 'a' => "hi", 'b' => nil, 'c' => "do"}

  x.each{ |k,v| x[k] = 'foo' unless v }

However, it is not always sane to alter something while you are
iterating over it. So,

  h = {}
  x.each{ |k,v| h[k] = v.nil? ? v : 'foo' }
  x.replace(h)

Or use Facets Enumerable#mash (alias #graph)

  require 'facets/enumerable/mash'

  x = x.mash{ |k,v| [k, v.nil? ? v : 'foo'] }

http://facets.rubyforge.org/doc/api/core/classes/E...

7.
A74096209c78118ff69d50a51129d697?d=identicon&s=25 Jason Lillywhite (jlillywh)
on 2008-11-05 08:56
Thank you!

However, I am getting undefined method 'mash' even though I do require
'facets/enumerable/mash'

am I missing something?
A74096209c78118ff69d50a51129d697?d=identicon&s=25 Jason Lillywhite (jlillywh)
on 2008-11-05 09:23
I guess since Enumerable is a Module, I need to do

include Enumerable... Thanks for the solution!
253bccb1f1236c92ca27edab089f74df?d=identicon&s=25 Sarcar, Shourya C (GE Healthcare) (Guest)
on 2008-11-05 11:54
(Received via mailing list)
> -----Original Message-----
> From: jason.lillywhite@gmail.com [mailto:jason.lillywhite@gmail.com]
> Sent: Wednesday, November 05, 2008 12:24 PM
> To: ruby-talk ML
> Subject: replace values in hash
>
> how would I iterate over a hash, such as
>
> x = { 'a' => "hi", 'b' => nil, 'c' => "do"}


 h.keys.each {|d| h[d] = "foo" if h[d] == nil}
45196398e9685000d195ec626d477f0e?d=identicon&s=25 Thomas Sawyer (7rans)
on 2008-11-05 16:33
(Received via mailing list)
On Nov 5, 2:54 am, Jason Lillywhite <jason.lillywh...@gmail.com>
wrote:
> Thank you!
>
> However, I am getting undefined method 'mash' even though I do require
> 'facets/enumerable/mash'
>
> am I missing something?

Don't think so. It's working fine for me.

What version of Ruby and Facets and what platform are you running?

T.
8666d1ebabcea440585dfe831a4af9f1?d=identicon&s=25 Brian Adkins (Guest)
on 2008-11-05 18:40
(Received via mailing list)
Jason Lillywhite <jason.lillywhite@gmail.com> writes:

> how would I iterate over a hash, such as
>
> x = { 'a' => "hi", 'b' => nil, 'c' => "do"}
>
> and replace nil values with 'foo' then return the hash again?

~/temp$ cat -b temp.rb
     1  require 'pp'

     2  class Hash
     3    def replace_value old, new
     4      self.inject({}) do |result,pair|
     5        k, v = pair[0], pair[1]
     6        result[k] = (v == old) ? new : v
     7        result
     8      end
     9    end
    10  end

    11  x = { 'a' => "hi", 'b' => nil, 'c' => "do", :d => nil }
    12  pp x
    13  y = x.replace_value(nil, 'foo')
    14  pp y
~/temp$ ruby temp.rb
{"a"=>"hi", "b"=>nil, :d=>nil, "c"=>"do"}
{"a"=>"hi", "b"=>"foo", "c"=>"do", :d=>"foo"}
45196398e9685000d195ec626d477f0e?d=identicon&s=25 Thomas Sawyer (7rans)
on 2008-11-05 19:13
(Received via mailing list)
On Nov 5, 10:31 am, Trans <transf...@gmail.com> wrote:
> Don't think so. It's working fine for me.
>
> What version of Ruby and Facets and what platform are you running?

For anyone who is interested, here's the definition (and some side
notes about how it evolved).

  def mash(&yld)
    if yld
      inject({}) do |h, *kv| # Used to be inject({}) do |h,kv|
        r = *yld[*kv]        # The *-op works different from to_a on
single element hash!!!
        nk, nv = *r          # Used to be nk, nv =
*yld[*kv].to_a.flatten
        h[nk] = nv
        h
      end
    else
      Enumerator.new(self,:mash)  # Used to be Hash[*self.to_a]
    end
  end

T.
90ebe8da17aabd36cc30d9f96a530e6f?d=identicon&s=25 James Herdman (biocsnerd)
on 2008-11-10 15:37
(Received via mailing list)
Not bad. Let's tighten it up a little:

class Hash
  def replace_value(old, new)
    self.inject({}) do |result, (key, existing_value)|
      result[key] = (value == old) ? new : existing_value
      result
    end
  end
end

This isn't bad, but you wouldn't want to do this for large Hashes since
you
end up copying the original.

James
This topic is locked and can not be replied to.