returning struct data as a hash in ruby

后端 未结 4 1559
我在风中等你
我在风中等你 2021-02-18 18:05

Is there a valid reason for there not being a method to return the data of a standard ruby struct as a hash (member, value pairs)? Seeing that structs and hashes have very simil

相关标签:
4条回答
  • 2021-02-18 18:27

    I don't think the use cases for hashes and structs are very similar. A hash lets you store a variable number of key-value pairs, and is suitable for storing thousands of pairs if a you want. No particular key is guaranteed to be present. With a Struct, you always know what the set of "keys" will be and it is usually small (less than 20).

    Hashes can be used to associate some piece of information with a large number of different objects. Hashes be used to specify optional parameters to a function. Structs can be used when you want to keep some well-defined pieces of information together in one object.

    I've never wanted to convert from the struct to a hash so I'm wondering why you do.

    EDIT 1: Did you know you can use this un-hash-like syntax with Structs?

    P = Struct.new(:x,:y)
    p = P.new(1,2)
    p.x  # => x
    

    EDIT 2: Hashes can also be used to look up objects quickly. obj_hashed_by_name[name] can be much faster than obj_array.find { |a| a.name == name }.

    0 讨论(0)
  • 2021-02-18 18:28

    (Ruby <= 1.9.3) OpenStruct has OpenStruct#marshall_dump and Struct has Struct#each_pair (use to_a to get the pairs and Hash+to_a to get the hash):

    Person = Struct.new(:name, :age)
    person = Person.new("Jamie", 23)
    person_hash = Hash[person.each_pair.to_a]
    #=> {:age=>23, :name=>"Jamie"}
    

    With Ruby 2.0 things are easier: Struct#to_h, OpenStruct#to_h:

    Person = Struct.new(:name, :age)
    person = Person.new("Jamie", 23)
    person_hash = person.to_h
    #=> {:age=>23, :name=>"Jamie"}
    
    0 讨论(0)
  • 2021-02-18 18:35

    The accepted answer did not work for me, i used the following instead

    require 'ostruct'
    require 'date'
    
    lid = OpenStruct.new(:status=>0,:rowversion=>0,:cre_dt=>DateTime.now.to_date,:cre_user=>'9999999')
    p Hash[lid.each_pair.to_a] #=> {}
    p lid.marshal_dump #=>{:status=>0, :rowversion=>0, :cre_dt=>#<Date: 2014-03-03 ((2456720j,0s,0n),+0s,2299161j)>, :cre_user=>"9999999"}
    
    0 讨论(0)
  • 2021-02-18 18:39

    I guess I don't know why you'd want to do it either, but:

    s.members.inject({}) { |m, f| m[f] = s[f]; m }
    

    Or, using each_with_object:

    s.members.each_with_object({}) { |m, h| h[m] = s[m] }
    
    0 讨论(0)
提交回复
热议问题