রুবি অবজেক্টকে হ্যাশে রূপান্তর করে


127

ধরা যাক আমার & এর Giftসাথে একটি বিষয় রয়েছে । এটি রুবেলে হ্যাশে রূপান্তর করার সর্বোত্তম উপায় কোনটি, পিলগুলি নয় (যদিও রেলেরও উত্তর দিতে নির্দ্বিধায় মনে হয়)?@name = "book"@price = 15.95{name: "book", price: 15.95}


16
@ উপহার.অ্যাট্রিবিউটস.টো_পশনগুলি কি করবে?
মিঃ এল

1
1) উপহার একটি অ্যাক্টিভেকর্ড অবজেক্ট? ২) আমরা কি নাম / @ দাম ধরে নিতে পারি যে কেবল উদাহরণের পরিবর্তনশীল নয়, তবে পাঠক অ্যাক্সেসরও? 3) আপনি কেবল নাম এবং দাম বা কোনও গিটারে সমস্ত গুণাবলী যা কিছু তা চান?
টোকল্যান্ড

@tokland, 1) কোন Giftহল ঠিক মত @nash সংজ্ঞায়িত করেছে ছাড়া, 2) নিশ্চিত, উদাহরণস্বরূপ ভেরিয়েবল পাঠক accessors থাকতে পারে। 3) উপহার সমস্ত গুণাবলী।
ma11 শেই 28

ঠিক আছে. উদাহরণস্বরূপ ভেরিয়েবল / পাঠকদের অ্যাক্সেস সম্পর্কে প্রশ্নটি ছিল কোনও বাইরের অ্যাক্সেস (ন্যাশ) বা অভ্যন্তরীণ পদ্ধতি (লেভিনালেক্স) চাইছে কিনা তা জানতে হবে। আমি "উত্তর" পদ্ধতির জন্য আমার উত্তর আপডেট করেছি।
টোকল্যান্ড

উত্তর:


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 ({}) has | 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। এটি কেবল কম্পিউটার বিজ্ঞান bad
নেট সিমার

সামান্য আরও সংক্ষিপ্ত:hash = Hash[gift.instance_variables.map { |var| [var.to_s[1..-1], gift.instance_variable_get(var)] } ]
মারভিনভিন

293

শুধু বলুন (বর্তমান বস্তু) .attributes

.attributesযে hashকোনও একটি প্রদান করে object। এবং এটি খুব পরিষ্কার।


138
মনে রাখবেন যে এটি একটি অ্যাক্টিভমডেল-নির্দিষ্ট পদ্ধতি, কোনও রুবি পদ্ধতি নয়।
ইটকার

6
সিকুয়েলের ক্ষেত্রে - ব্যবহার করুন .values: সিক্যুয়েল.জেরেমিভানস.এন.আরডোক / স্লাসস
ডিমিটারভিপি

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
আসলে না. আরডোক ডকুমেন্টেশন বলছে: Use :: for describing class methods, # for describing instance methods, and use . for example code(উত্স: রুবি- ডক.অর্গ.অ। / ডকুমেন্টেশন- গাইডলাইনস html ) এছাড়াও, সরকারী নথিপত্র (যেমন রুবি চ্যাঙ্গেলওগ , github.com/ruby/ruby/blob/v2_1_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) }
anothermh

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 পদ্ধতিতে অন্য তৈরি করার দরকার নেই। ভালো লেগেছে: অ্যাট্রিবিউট_নেমস। এচ_ইথ_বজেক্ট ({}) name | নাম, অ্যাটর্স | অ্যাট্রেসস [নাম] = পঠন_প্রেম (নাম)}} এখানে দেখুন: 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পছন্দসই হ্যাশ ফিরিয়ে দেওয়ার জন্য আপনার নিজের অবজেক্টের পদ্ধতিটি , বা কেবলমাত্র ডিফল্ট অবজেক্টের আচরণকে ওভাররাইড না করে একটি অনুরূপ পদ্ধতি প্রয়োগ করা উচিত।

যদি আপনি ফ্যানসিয়ার পেতে চান তবে আপনি অবজেক্ট.ইনস্ট্যান্স_ভেরিয়েবলগুলির সাথে কোনও অবজেক্টের উদাহরণ ভেরিয়েবলগুলি দিয়ে পুনরাবৃত্তি করতে পারেন


4

'হ্যাশেবল' মণি ( 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}}]}


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}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.