Jak przekonwertować skrót na strukturę w ruby?Konwertowanie skrótu do struktury
Biorąc pod uwagę to:
h = { :a => 1, :b => 2 }
Chcę struct takie, że:
s.a == 1
s.b == 2
Jak przekonwertować skrót na strukturę w ruby?Konwertowanie skrótu do struktury
Biorąc pod uwagę to:
h = { :a => 1, :b => 2 }
Chcę struct takie, że:
s.a == 1
s.b == 2
Jeśli nie konkretnie h ave być Struct
a zamiast tego może być OpenStruct
:
pry(main)> require 'ostruct'
pry(main)> s = OpenStruct.new(h)
=> #<OpenStruct a=1, b=2>
pry(main)> puts s.a, s.b
1
2
Poniższa tworzy struct od mieszania w wiarygodny sposób (gdyż kolejność mieszania nie jest gwarantowana w Ruby) :
s = Struct.new(*(k = h.keys)).new(*h.values_at(*k))
Ponieważ kolejność klucz Hash jest gwarantowana w Ruby 1.9+:
Struct.new(*h.keys).new(*h.values)
Dobrze wiedzieć.Chociaż gdzieś to czytałem, ale nie pamiętałem, gdzie. Dzięki! – alf
To nie działa (przynajmniej w Rubim 2.2.0): 'Struct.new (* h.keys) podnosi:' NameError: identyfikator mój_key musi być stały' – Joe
@Joe działa dobrze. Myślę, że użyłeś kluczy łańcuchowych dla twojego skrótu, co jest przyczyną błędu. Błąd mówi, że potrzebuje stałej wartości, tj. Symbolu zamiast łańcucha. Mogę repro błąd w 2.1.5, odchodzi, jeśli przejdę do symbolu. – ehsanul
Oto przykład do mapowania wartości w odpowiedniej kolejności z struct:
require 'securerandom'
Message = Struct.new(:to, :from, :message, :invitee)
message_params = {from: "[email protected]", to: "[email protected]",
invitee: SecureRandom.uuid, message: "hello"}
if Message.members.sort == message_params.keys.sort
# Do something with the return struct object here
Message.new *Message.members.map {|k| message_params[k] }
else
raise "Invalid keys for Message"
end
Jeśli już struct zdefiniowane, a chcesz instancji wystąpienie z hash:
Person = Struct.new(:first_name, :last_name, :age)
person_hash = { first_name: "Foo", last_name: "Bar", age: 29 }
person = Person.new(*person_hash.values_at(*Person.members))
=> #<struct Person first_name="Foo", last_name="Bar", age=29>
To powinna być zaakceptowana odpowiedź :). Dzięki! – Ven
Dziękujemy! Projektuję klejnot, który można wywołać z komendy lub z zewnętrznego kodu, z których każda dostarcza opcji (odpowiednio przy użyciu OptionParser lub Hash). Pozwala to na łatwe filtrowanie opcji podczas inicjalizacji mojego klejnotu. A Struct pomaga również w "samodzielnym dokumentowaniu" dozwolonych opcji! – Excalibur
require 'ds_hash'
data = {a: {b: 123 }}.to_struct
data.a.b == 123 # true
data.a == {b: 123 } # true
Mając Hash#to_struct
jest bardzo praktyczny:
class Hash
def to_struct
Struct.new(*keys).new(*values)
end
end
a niektóre przykłady:
>> { a: 1, b: 2 }.to_struct
=> #<struct a=1, b=2>
>> { a: 1, b: 2 }.to_struct.a
=> 1
>> { a: 1, b: 2 }.to_struct.b
=> 2
>> { a: 1, b: 2 }.to_struct.c
NoMethodError: undefined method `c` for #<struct a=1, b=2>
Głębokie to_struct
który współpracuje z tablicami:
class Array
def to_struct
map { |value| value.respond_to?(:to_struct) ? value.to_struct : value }
end
end
class Hash
def to_struct
Struct.new(*keys).new(*values.to_struct)
end
end
To dobrze, ale jeśli jego json hash '['name']', musi symbolizować klucze. – 7urkm3n
Nigdy wcześniej nie słyszałem o "OpenStruct". To bardzo fajnie! Dzięki! – alf
Należy pamiętać, że OpenStructs może być niezwykle powolny w użyciu. W porządku dla małej liczby małych obiektów, ale skalują się bardzo źle. Niektóre dalej informacji tutaj: http://stackoverflow.com/questions/1177594/ruby-struct-vs-openstruct –
@AFaderDarkly Myślę, że ich problemy prędkości są dobrze udokumentowane, ale dzięki. –