在Ruby中将结构化数据作为哈希返回

27

是否有正当理由没有一种方法将标准Ruby结构的数据返回为哈希表(成员,值对)的形式?鉴于结构和哈希表具有非常相似的用例,我很惊讶为什么没有这样的方法存在。或者说,它确实存在,只是我太糊涂了?

实现这种功能很容易(我现在已经做到了),但标准库中缺乏此类功能,使我思考我可能并没有真正掌握Ruby中的结构概念。

4个回答

47

Ruby <= 1.9.3具有OpenStruct#marshall_dumpStruct#each_pair功能:

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

Ruby 2.0提供了Struct#to_hOpenStruct#to_h

Person = Struct.new(:name, :age)
person = Person.new("Jamie", 23)
person_hash = person.to_h
#=> {:age=>23, :name=>"Jamie"}

感谢这个“无需注入”的解决方案,更重要的是感谢提供了OpenStruct具有这样一个方法的信息,这在一定程度上回答了我的问题,即询问Ruby Struct是否可以实现这样的功能(显然可以)。 - cvshepherd
正是这些改进使得随着时间的推移,Ruby变得越来越令人愉悦使用。喜欢它。 - Joshua Pinter

4
我认为哈希和结构体的用途并不相似。哈希允许您存储可变数量的键值对,如果需要,适合存储成千上万个键值对。没有保证任何特定的键一定存在。而结构体则总是知道将要使用的“键”的集合,通常很小(少于20个)。
哈希可以用来将某些信息与大量不同的对象关联起来。哈希可用于指定函数的可选参数。当您想要将一些明确定义的信息组合在一个对象中时,可以使用结构体。
我从未想过从结构体转换为哈希,所以我想知道您为什么这样做。
编辑1: 您是否知道可以使用此类似非哈希语法与结构体?
P = Struct.new(:x,:y)
p = P.new(1,2)
p.x  # => x
编辑 2: 哈希表也可以用于快速查找对象。 obj_hashed_by_name[name]obj_array.find { |a| a.name == name } 快得多。

1
我仍然看不出为什么不能将成员值对作为哈希检索。特别是考虑到结构体完全可以像数组一样运作,这在某些情况下确实很方便,但是没有上下文(成员)获取结构体的值大多数时候似乎毫无用处。 - cvshepherd

2

我猜我也不知道为什么你想这样做,但是:

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

或者,使用 each_with_object :
s.members.each_with_object({}) { |m, h| h[m] = s[m] }

我需要/想要这个的原因是为了能够按数值排序,哈希表可以很好地完成这个任务。 - cvshepherd
1
@cvshepherd 啊,我想我会使用一个类,但现在我明白了 :) - Dave Newton

0

被接受的答案对我不起作用,我使用了以下代替

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接