रूबी वस्तु को हैश में परिवर्तित करती है


127

चलो कहते हैं कि मैं एक है Giftके साथ वस्तु @name = "book"और @price = 15.95{name: "book", price: 15.95}रूबी में हैश को बदलने का सबसे अच्छा तरीका क्या है , न कि रेल (हालांकि बेझिझक रेल का जवाब भी देना है)?


16
क्या @ gift.attributes.to_options करेंगे?
श्री एल

1
1) क्या उपहार एक ActiveRecord वस्तु है? 2) क्या हम मान सकते हैं @ नाम / @ कीमत केवल उदाहरण चर नहीं बल्कि पाठक एक्सेसर्स भी हैं? 3) आप उपहार में केवल नाम और मूल्य या सभी विशेषताएँ चाहते हैं, चाहे वे कुछ भी हों?
टोकन

@tokland, 1) नहीं, बिल्कुल वैसाGift ही है जैसे @nash ने परिभाषित किया है , 2 को छोड़कर), निश्चित रूप से, उदाहरण चर में अलग-अलग सहायक उपकरण हो सकते हैं। 3) उपहार में सभी गुण।
ma11hew28

ठीक। उदाहरण चर / पाठकों की पहुंच के बारे में सवाल यह जानना था कि क्या बाहर की पहुँच (नश) या अंदर की विधि (लेविनैलेक्स) चाहिए थी। मैंने "अंदर" दृष्टिकोण के लिए अपना उत्तर अपडेट किया।
टोकन

जवाबों:


80
class Gift
  def initialize
    @name = "book"
    @price = 15.95
  end
end

gift = Gift.new
hash = {}
gift.instance_variables.each {|var| hash[var.to_s.delete("@")] = gift.instance_variable_get(var) }
p hash # => {"name"=>"book", "price"=>15.95}

वैकल्पिक रूप से each_with_object:

gift = Gift.new
hash = gift.instance_variables.each_with_object({}) { |var, hash| hash[var.to_s.delete("@")] = gift.instance_variable_get(var) }
p hash # => {"name"=>"book", "price"=>15.95}

3
आप चर को आरंभ करने के लिए इंजेक्शन का उपयोग कर सकते हैं: gift.instance_variables.inject ({}) {| hash, var | हैश [var.to_s.delete ("@")] = gift.instance_variable_get (var); हैश}
जॉर्डन

8
अच्छा लगा। मैंने प्रतीकों को प्राप्त करने के लिए प्रतिस्थापित var.to_s.delete("@")किया var[1..-1].to_sym
ma11hew28

3
इंजेक्शन का उपयोग न करें, gift.instance_variables.each_with_object({}) { |var,hash| hash[var.to_s.delete("@")] = gift.instance_variable_get(var) }; hash
ट्रेसिंग

1
मैं रूबी बुत के लिए कभी नहीं समझूंगा eachmapऔर injectबहुत अधिक शक्तिशाली हैं। यह एक डिजाइन योग्यता है जो मेरे पास रूबी के पास है: mapऔर injectइसके साथ लागू की जाती है each। यह केवल बुरा कंप्यूटर विज्ञान है।
नैट सीमर

थोड़ा और अधिक संक्षिप्त:hash = Hash[gift.instance_variables.map { |var| [var.to_s[1..-1], gift.instance_variable_get(var)] } ]
मार्विन

293

बस कहें (वर्तमान वस्तु) .attributes

.attributeshashकिसी का भी लौटाता है object। और यह बहुत क्लीनर भी है।


138
ध्यान दें कि यह एक ActiveModel- विशिष्ट विधि है, रूबी विधि नहीं।
ईंट

6
सीक्वल के मामले में - उपयोग करें .values: अगली कड़ी। jeremyevans.net/rdoc/classes/Sequel/Model/…
dimitarvp

instance_valuesसमान उत्पादन के लिए सभी रूबी वस्तुओं के लिए इस्तेमाल किया जा सकता है।
बिशाल

48

लागू #to_hash?

class Gift
  def to_hash
    hash = {}
    instance_variables.each { |var| hash[var.to_s.delete('@')] = instance_variable_get(var) }
    hash
  end
end


h = Gift.new("Book", 19).to_hash

तकनीकी रूप से, यह .to_hash होना चाहिए, क्योंकि # वर्ग विधियों को इंगित करता है।
कालेब

6
दरअसल नहीं। RDoc प्रलेखन कहता है: Use :: for describing class methods, # for describing instance methods, and use . for example code(स्रोत: ruby-doc.org/documentation-guidelines.html ) इसके अलावा, आधिकारिक प्रलेखन (जैसे माणिक CHANGELOG, github.com/ruby/ruby/blob/v2b_0/NEWS ) #उदाहरण के तरीकों और डॉट का उपयोग करता है लगातार कक्षा के तरीकों के लिए।
लेविनलेक्स

कृपया इस एंटीपैटर्न के बजाय इंजेक्शन का उपयोग करें।
YoTengoUnLCD

वन-लाइनर वेरिएंट का उपयोग each_with_object:instance_variables.each_with_object(Hash.new(0)) { |element, hash| hash["#{element}".delete("@").to_sym] = instance_variable_get(element) }
दूसरा मार्म

43
Gift.new.instance_values # => {"name"=>"book", "price"=>15.95}

10
यह रेल है, रूबी के पास ही नहीं है instance_values। ध्यान दें कि मैट ने रूबी के लिए रास्ता पूछा, विशेष रूप से रेल नहीं।
क्रिस्टोफर क्रुत्ज़िग

28
उन्होंने यह भी कहा कि बेझिझक रेल का जवाब भी देना चाहिए ... इसलिए मैंने किया।
एरिक रीडस्ट्रॉम

भगवान दोनों संस्करणों को देखने के लिए यहां;) इसे पसंद किया
सेबस्टियन शूर्मन

17

आप as_jsonविधि का उपयोग कर सकते हैं । यह आपकी वस्तु को हैश में परिवर्तित कर देगा।

लेकिन, वह हैश उस वस्तु के नाम के लिए एक मूल्य के रूप में आएगा। आपके मामले में,

{'gift' => {'name' => 'book', 'price' => 15.95 }}

यदि आपको कोई हैश चाहिए जो ऑब्जेक्ट उपयोग में संग्रहीत हो as_json(root: false)। मुझे लगता है कि डिफ़ॉल्ट रूट गलत होगा। अधिक जानकारी के लिए आधिकारिक रूबी गाइड देखें

http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json


13

सक्रिय रिकॉर्ड ऑब्जेक्ट के लिए

module  ActiveRecordExtension
  def to_hash
    hash = {}; self.attributes.each { |k,v| hash[k] = v }
    return hash
  end
end

class Gift < ActiveRecord::Base
  include ActiveRecordExtension
  ....
end

class Purchase < ActiveRecord::Base
  include ActiveRecordExtension
  ....
end

और फिर कॉल करें

gift.to_hash()
purch.to_hash() 

2
मज़ेदार यह रेल ढांचे का हिस्सा नहीं है। वहाँ होने के लिए एक उपयोगी चीज की तरह लगता है।
मैग्ने

गुण विधि मानों के साथ एक नया हैश लौटाती है - इसलिए to_hash विधि में एक और बनाने की आवश्यकता नहीं है। जैसे: विशेषता_नमी.च_च_हथ_बोल ({}) {| नाम, अटेर्स | attrs [नाम] = read_attribute (नाम)}। यहाँ देखें: github.com/rails/rails/blob/master/activerecord/lib/…
क्रिस किम्प्टन

आप नक्शे के साथ ऐसा कर सकते थे, आपका साइड इफ़ेक्ट इम्प्लीमेंटेशन मेरे दिमाग को चोट पहुँचा रहा है!
नैट सीमर


11
class Gift
  def to_hash
    instance_variables.map do |var|
      [var[1..-1].to_sym, instance_variable_get(var)]
    end.to_h
  end
end

6

आप एक कार्यात्मक शैली का उपयोग करके एक बहुत ही सुंदर समाधान लिख सकते हैं।

class Object
  def hashify
    Hash[instance_variables.map { |v| [v.to_s[1..-1].to_sym, instance_variable_get v] }]
  end
end

4

आपको inspectइच्छित हैश को वापस करने के लिए अपनी वस्तु की विधि को ओवरराइड करना चाहिए , या डिफ़ॉल्ट ऑब्जेक्ट व्यवहार को ओवरराइड किए बिना एक समान विधि को लागू करना चाहिए।

यदि आप कट्टर होना चाहते हैं, तो आप ऑब्जेक्ट के इंस्टेंस चर के साथ ऑब्जेक्ट.instance_variables पर पुनरावृति कर सकते हैं


4

पुन: 'hashes' रत्न ( https://rubygems.org/gems/hashable ) उदाहरण का उपयोग करके अपनी वस्तुओं को हैश में बदलें

class A
  include Hashable
  attr_accessor :blist
  def initialize
    @blist = [ B.new(1), { 'b' => B.new(2) } ]
  end
end

class B
  include Hashable
  attr_accessor :id
  def initialize(id); @id = id; end
end

a = A.new
a.to_dh # or a.to_deep_hash
# {:blist=>[{:id=>1}, {"b"=>{:id=>2}}]}

4

कोशिश करना चाह सकते हैं instance_values। मेरे लिए यही काम किया।


1

केवल मॉडल विशेषताओं के हैश ऑब्जेक्ट के रूप में एक उथले प्रति पैदा करता है

my_hash_gift = gift.attributes.dup

परिणामी वस्तु के प्रकार की जाँच करें

my_hash_gift.class
=> Hash

0

यदि आपको नेस्टेड ऑब्जेक्ट्स को भी रूपांतरित करने की आवश्यकता है।

# @fn       to_hash obj {{{
# @brief    Convert object to hash
#
# @return   [Hash] Hash representing converted object
#
def to_hash obj
  Hash[obj.instance_variables.map { |key|
    variable = obj.instance_variable_get key
    [key.to_s[1..-1].to_sym,
      if variable.respond_to? <:some_method> then
        hashify variable
      else
        variable
      end
    ]
  }]
end # }}}


0

रेल के बिना ऐसा करने के लिए, एक साफ तरीका एक स्थिर पर विशेषताओं को संग्रहीत करना है।

class Gift
  ATTRIBUTES = [:name, :price]
  attr_accessor(*ATTRIBUTES)
end

और फिर, उदाहरण के Giftलिए Hash, आप कर सकते हैं:

class Gift
  ...
  def to_h
    ATTRIBUTES.each_with_object({}) do |attribute_name, memo|
      memo[attribute_name] = send(attribute_name)
    end
  end
end

यह ऐसा करने का एक अच्छा तरीका है क्योंकि इसमें केवल वही शामिल होगा जो आप परिभाषित करते हैं attr_accessor, और हर उदाहरण चर नहीं।

class Gift
  ATTRIBUTES = [:name, :price]
  attr_accessor(*ATTRIBUTES)

  def create_random_instance_variable
    @xyz = 123
  end

  def to_h
    ATTRIBUTES.each_with_object({}) do |attribute_name, memo|
      memo[attribute_name] = send(attribute_name)
    end
  end
end

g = Gift.new
g.name = "Foo"
g.price = 5.25
g.to_h
#=> {:name=>"Foo", :price=>5.25}

g.create_random_instance_variable
g.to_h
#=> {:name=>"Foo", :price=>5.25}

0

मैंने हैश रूपांतरणों को आसान बनाने के लिए संरचनाओं का उपयोग करना शुरू कर दिया। एक नंगे ढांचे का उपयोग करने के बजाय मैं एक हैश से अपना स्वयं का वर्ग तैयार करता हूं इससे आप अपने स्वयं के कार्यों को बना सकते हैं और यह एक वर्ग के गुणों का दस्तावेजीकरण करता है।

require 'ostruct'

BaseGift = Struct.new(:name, :price)
class Gift < BaseGift
  def initialize(name, price)
    super(name, price)
  end
  # ... more user defined methods here.
end

g = Gift.new('pearls', 20)
g.to_h # returns: {:name=>"pearls", :price=>20}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.