Возвращать данные структуры как хэш в рубине

Есть ли веская причина, почему не существует метода для возврата данных стандартной структуры 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"}