How can I marshal a hash with arrays?

前端 未结 4 1855
醉话见心
醉话见心 2021-01-24 04:23

What should I do to marshal an hash of arrays? The following code only prints {}.

s = Hash.new
s.default = Array.new
s[0] <<          


        
相关标签:
4条回答
  • 2021-01-24 05:03

    You can just create your hash structure while initialing Hash.new to avoid such trouble

    h = Hash.new{ |a,b| a[b] = [] }
    h[:my_key] << "my value"
    
    0 讨论(0)
  • 2021-01-24 05:13
    s = Hash.new
    s.default = Array.new
    s[0] << "Tigger"
    s[7] << "Ruth"
    s[7] << "Puuh"
    

    This code changes the default 3 times (which is probably what showed up in the dump), but it does not store anything in the hash. Try "puts s[8]", it will return [["Tigger"], ["Ruth"], ["Puuh"]].

    A Hash.default_proc will do what you want

    s = Hash.new{|hash,key| hash[key]=[] }
    

    But you can't marshall a proc. This will work:

    s = Hash.new
    s.default = Array.new
    s[0] += ["Tigger"]
    s[7] += ["Ruth"]
    s[7] += ["Puuh"]
    

    This works because []+=["Tigger"] creates a new array. An alternative, creating less arrays:

    s = Hash.new
    (s[0] ||= []) << "Tigger"
    (s[7] ||= []) << "Ruth"
    (s[7] ||= []) << "Puuh"
    

    Only creates a new array when the key is absent (nil).

    0 讨论(0)
  • 2021-01-24 05:14

    As you can't use Marshall.dump on a Hash with a proc for the default element, you could use a slightly more roundabout way of appending to each Array instead of <<:

    s = Hash.new
    s.default = []
    s[0] += [ "Tigger" ]
    s[7] += [ "Ruth" ]
    s[7] += [ "Pooh" ]
    data = Marshal.dump(s)
    ls = Marshal.restore(data)
    p ls
    
    0 讨论(0)
  • 2021-01-24 05:21

    You might be misled about how Hash.default works.

    Before you Marshal.dump, print the data structure. It is {}. That's because you are concatenating each string into nil, not into an empty array. The code below illustrates and solves your problem.

    s = Hash.new
    s.default = Array.new
    s[0] = []
    s[0] << "Tigger"
    s[7] = []
    s[7] << "Ruth"
    s[7] << "Puuh"
    p s
    data = Marshal.dump(s)
    ls = Marshal.restore( data )
    p ls
    

    Returns:

    {0=>["Tigger"], 7=>["Ruth", "Puuh"]}
    {0=>["Tigger"], 7=>["Ruth", "Puuh"]}
    

    EDIT:

    I insert a lot of data into the hash

    So maybe some helper code would make the insertion process smoother:

    def append_to_hash(hash, position, obj)
      hash[position] = [] unless hash[position]
      hash[position] << obj
    end
    
    s = Hash.new
    append_to_hash(s, 0, "Tigger")
    append_to_hash(s, 7, "Ruth")
    append_to_hash(s, 7, "Puuh")
    s.default = Array.new // this is only for reading
    p s
    data = Marshal.dump(s)
    ls = Marshal.restore( data )
    p ls
    
    0 讨论(0)
提交回复
热议问题