replace values in hash

Discussion in 'Ruby' started by Jason Lillywhite, Nov 5, 2008.

  1. 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?
    Jason Lillywhite, Nov 5, 2008
    1. Advertisements

  2. Jason Lillywhite

    Trans Guest

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

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

    h =3D {}
    x.each{ |k,v| h[k] =3D v.nil? ? v : 'foo' }

    Or use Facets Enumerable#mash (alias #graph)

    require 'facets/enumerable/mash'

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

    Trans, Nov 5, 2008
    1. Advertisements

  3. Thank you!

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

    am I missing something?
    Jason Lillywhite, Nov 5, 2008
  4. =20

    h.keys.each {|d| h[d] =3D "foo" if h[d] =3D=3D nil}
    Sarcar, Shourya C (GE Healthcare), Nov 5, 2008
  5. Jason Lillywhite

    Trans Guest

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

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

    Trans, Nov 5, 2008
  6. Jason Lillywhite

    Brian Adkins Guest

    ~/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"}
    Brian Adkins, Nov 5, 2008
  7. Jason Lillywhite

    Trans Guest

    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 =3D *yld[*kv] # The *-op works different from to_a on
    single element hash!!!
    nk, nv =3D *r # Used to be nk, nv =3D
    h[nk] =3D nv
    else,:mash) # Used to be Hash[*self.to_a]

    Trans, Nov 5, 2008
  8. [Note: parts of this message were removed to make it a legal post.]

    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

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


    James Herdman, Nov 10, 2008
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.