Возвращать данные структуры как хэш в рубине
Есть ли веская причина, почему не существует метода для возврата данных стандартной структуры ruby как хэш (пары членов, значений)?
Увидев, что структуры и хеши имеют очень похожие варианты использования, я удивлен, что такой метод не существует. Или делает это, и я слишком слеп?
Легко реализовать (и я сделал это сейчас), но отсутствие такой функциональности в стандартных libs, мне кажется, что я, возможно, не понял концепцию структур в ruby.
Ответы
Ответ 1
(Ruby <= 1.9.3) OpenStruct
имеет OpenStruct # marshall_dump и Struct
имеет Struct # each_pair (используйте to_a
, чтобы получить пары и Hash
+ to_a
, чтобы получить хэш):
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_h, OpenStruct # to_h:
Person = Struct.new(:name, :age)
person = Person.new("Jamie", 23)
person_hash = person.to_h
#=> {:age=>23, :name=>"Jamie"}
Ответ 2
Я не думаю, что случаи использования хешей и структур очень похожи. Хэш позволяет хранить переменное число пар ключ-значение и подходит для хранения тысяч пар, если вы хотите. Никакой конкретный ключ не будет присутствовать. С помощью Struct вы всегда знаете, какой будет набор "ключей", и он обычно мал (менее 20).
Хеши могут использоваться для связывания некоторой части информации с большим количеством разных объектов. Хеши используются для указания необязательных параметров для функции. Структуры могут использоваться, когда вы хотите сохранить некоторые четко определенные фрагменты информации в одном объекте.
Я никогда не хотел конвертировать из структуры в хэш, поэтому мне интересно, почему вы это делаете.
РЕДАКТИРОВАТЬ 1:
Знаете ли вы, что вы можете использовать этот синтаксис не-хэш-типа с помощью Structs?
P = Struct.new(:x,:y)
p = P.new(1,2)
p.x # => x
EDIT 2: хэши также могут использоваться для быстрого поиска объектов. obj_hashed_by_name[name]
может быть намного быстрее, чем obj_array.find { |a| a.name == name }
.
Ответ 3
Я думаю, я не знаю, зачем вам это нужно, но:
s.members.inject({}) { |m, f| m[f] = s[f]; m }
Или, используя each_with_object
:
s.members.each_with_object({}) { |m, h| h[m] = s[m] }
Ответ 4
Принятый ответ не сработал у меня, я использовал вместо этого
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"}