returning struct data as a hash in ruby

2020-07-01 15:03发布

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 similar use cases, I'm surprised that no such method exists. Or does it, and I'm just too blind?

It's easy to implement (and i have done so for now), but lack of such functionality in the standard libs, has me thinking that I might have not really grasped the concept of structs in ruby.

标签: ruby
4条回答
乱世女痞
2楼-- · 2020-07-01 15: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"}
查看更多
我命由我不由天
3楼-- · 2020-07-01 15:29

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] }
查看更多
手持菜刀,她持情操
4楼-- · 2020-07-01 15:31

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 }.

查看更多
做个烂人
5楼-- · 2020-07-01 15:36

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"}
查看更多
登录 后发表回答