কিভাবে হ্যাশ মান পরিবর্তন করতে?


126

আমি প্রতিটি valueহ্যাশের সাথে প্রতিস্থাপন করতে চাই value.some_method

উদাহরণস্বরূপ, একটি সাধারণ হ্যাশ দেওয়া জন্য:

{"a" => "b", "c" => "d"}` 

প্রতিটি মান .upcased হওয়া উচিত , সুতরাং দেখে মনে হচ্ছে:

{"a" => "B", "c" => "D"}

আমি চেষ্টা #collectএবং #mapকিন্তু সবসময় শুধু অ্যারে ফিরুন। এটি করার জন্য কি কোনও মার্জিত উপায় আছে?

হালনাগাদ

অভিশাপ, আমি ভুলে গিয়েছি: হ্যাশ একটি উদাহরণে পরিবর্তনশীল যা পরিবর্তন করা উচিত নয়। পরিবর্তিত মানগুলির সাথে আমার একটি নতুন হ্যাশ দরকার, তবে সেই পরিবর্তনশীলটিকে স্পষ্টভাবে সংজ্ঞায়িত না করা এবং তারপরে হ্যাশটি পূরণ করে লুপ করতে পছন্দ করব। কিছুটা এইরকম:

new_hash = hash.magic{ ... }

আমার উত্তরের দ্বিতীয় উদাহরণটি একটি নতুন হ্যাশ দেয়। আপনি যদি চান # যন্ত্রে যে যাদুটি করা হচ্ছে সে সম্পর্কে আমাকে প্রসারিত করতে চাইলে তাতে মন্তব্য করুন।
kch

উত্তর:


218
my_hash.each { |k, v| my_hash[k] = v.upcase } 

বা, আপনি যদি এটি অ-ধ্বংসাত্মকভাবে করতে পছন্দ করেন এবং পরিবর্তনের পরিবর্তে একটি নতুন হ্যাশ ফিরিয়ে দিন my_hash:

a_new_hash = my_hash.inject({}) { |h, (k, v)| h[k] = v.upcase; h } 

এই শেষ সংস্করণে অতিরিক্ত সুবিধা রয়েছে যা আপনি কীগুলিও রূপান্তর করতে পারেন।


26
প্রথম পরামর্শটি উপযুক্ত নয়; পুনরাবৃত্তির সময় একটি পরিগণিত উপাদানকে সংশোধন করা অনির্ধারিত আচরণের দিকে পরিচালিত করে - এটি অন্যান্য ভাষায়ও বৈধ। এখানে ম্যাজ
মার্কাস

4
@ মার্কাস আমি সম্মত হই যে সাধারণভাবে এ জাতীয় পরিবর্তন এড়ানো উচিত। তবে এই ক্ষেত্রে এটি সম্ভবত নিরাপদ, কারণ পরিবর্তনটি ভবিষ্যতের পুনরাবৃত্তিকে পরিবর্তন করে না। এখন যদি অন্য কী (যা এটি ব্লকটিতে পাস করা হয়নি) বরাদ্দ করা হয়, তবে সমস্যা হবে।
কেলভিন

36
আপনি যখন হ্যাশ দিয়ে ব্লকটি শেষ করতে চান না তখন @ অ্যাডাম @ কেএইচ each_with_objectএকটি আরও সুবিধাজনক সংস্করণ inject:my_hash.each_with_object({}) {|(k, v), h| h[k] = v.upcase }
কেলভিন

6
জোড়ের তালিকাকে হ্যাশে রূপান্তর করার জন্য খুব ঝরঝরে বাক্য গঠন রয়েছে, যাতে আপনি লিখতে পারেনa_new_hash = Hash[ my_hash.map { |k, v| [k, v.upcase] } ]
পুনরায়

2
রুবি 2 দিয়ে আপনি লিখতে পারেন.to_h
রোমান-রোমান


35

আপনি মানগুলি সংগ্রহ করতে পারেন এবং অ্যারে থেকে আবার হ্যাশ রূপান্তর করতে পারেন।

এটার মত:

config = Hash[ config.collect {|k,v| [k, v.upcase] } ]

23

এটি এটি করবে:

my_hash.each_with_object({}) { |(key, value), hash| hash[key] = value.upcase }

injectসুবিধার বিপরীতে হ'ল আপনাকে ব্লকের ভিতরে আবার হ্যাশ ফিরিয়ে দেওয়ার দরকার নেই।


আমি পছন্দ করি যে এই পদ্ধতিটি মূল হ্যাশটি সংশোধন করে না।
খ্রিস্টান ডি লোরেঞ্জো

10

এই ফাংশনটি ব্যবহার করে দেখুন:

h = {"a" => "b", "c" => "d"}
h.each{|i,j| j.upcase!} # now contains {"a" => "B", "c" => "D"}.

5
এটি ভাল, তবে এটি লক্ষ্য করা উচিত যে এটি কেবল তখনই কাজ করে যখন জে এর একটি ধ্বংসাত্মক পদ্ধতি থাকে যা নিজে কাজ করে। সুতরাং এটি সাধারণ মানটি পরিচালনা করতে পারে না ome
kch

ভাল পয়েন্ট, এবং তার আপডেটের সাথে আপনার দ্বিতীয় সমাধানটি (অ-ধ্বংসাত্মক) সবচেয়ে ভাল।
ক্রিস ডগেট 18

10

অ্যাক্টিভসপোর্ট v4.2.0 এ এর জন্য একটি পদ্ধতি রয়েছে। এটি বলা হয় transform_valuesএবং মূলত প্রতিটি কী-মান-জুটির জন্য একটি ব্লক কার্যকর করে।

যেহেতু তারা এটির সাথে কাজ করছে eachআমি মনে করি এটি লুপ করার চেয়ে ভাল উপায় আর নেই।

hash = {sample: 'gach'}

result = {}
hash.each do |key, value|
  result[key] = do_stuff(value)
end

হালনাগাদ:

রুবি ২.৪.০ থেকে আপনি স্থানীয়ভাবে ব্যবহার করতে পারেন #transform_valuesএবং #transform_values!


2

আপনি আরও এক ধাপ এগিয়ে যেতে এবং নেস্টেড হ্যাশটিতে এটি করতে চাইতে পারেন। অবশ্যই এটি রেল প্রকল্পগুলির সাথে মোটামুটি পরিমাণে ঘটে।

প্যারামের হ্যাশটি ইউটিএফ -8 এ রয়েছে তা নিশ্চিত করার জন্য এখানে কিছু কোড রয়েছে:

  def convert_hash hash
    hash.inject({}) do |h,(k,v)|
      if v.kind_of? String
        h[k] = to_utf8(v) 
      else
        h[k] = convert_hash(v)
      end
      h
    end      
  end    

  # Iconv UTF-8 helper
  # Converts strings into valid UTF-8
  #
  # @param [String] untrusted_string the string to convert to UTF-8
  # @return [String] your string in UTF-8
  def to_utf8 untrusted_string=""
    ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
    ic.iconv(untrusted_string + ' ')[0..-2]
  end  

1

আমি এরকম কিছু করি:

new_hash = হ্যাশ [* আসল_হ্যাশ.লোক {| কী, মান | [কী, মান +1] flat। সমতল]

এটি আপনাকে যে কোনও অভিব্যক্তির মাধ্যমে কী বা মানকে রূপান্তর করার সুবিধা সরবরাহ করে (এবং এটি অবশ্যই ধ্বংসাত্মক)।


1

রুবির কাছে এমন tapপদ্ধতি রয়েছে ( 1.8.7 , 1.9.3 এবং 2.1.0 ) যা এই জাতীয় স্টাফের জন্য খুব দরকারী।

original_hash = { :a => 'a', :b => 'b' }
original_hash.clone.tap{ |h| h.each{ |k,v| h[k] = v.upcase } }
# => {:a=>"A", :b=>"B"}
original_hash # => {:a=>"a", :b=>"b"}

1

পাগল-নির্দিষ্ট

যদি কারও কাছে কেবলমাত্র to_sপ্রতিটি মানটিতে পদ্ধতি কল করার প্রয়োজন হয় এবং সেগুলি 4.2 ব্যবহার করে না (যা transform_valuesপদ্ধতির লিঙ্কটি অন্তর্ভুক্ত ), আপনি নিম্নলিখিতটি করতে পারেন:

original_hash = { :a => 'a', :b => BigDecimal('23.4') }
#=> {:a=>"a", :b=>#<BigDecimal:5c03a00,'0.234E2',18(18)>}
JSON(original_hash.to_json)
#=> {"a"=>"a", "b"=>"23.4"}

দ্রষ্টব্য: 'json' লাইব্রেরির ব্যবহার প্রয়োজন।

দ্রষ্টব্য 2: এটি কীগুলিকে পাশাপাশি স্ট্রিংগুলিতে পরিণত করবে


1

যদি আপনি জানেন যে মানগুলি স্ট্রিং হয় তবে আপনি প্রতিস্থাপনটি কল করতে পারেন হয় তবে আপনি চক্রের সময় তাদের পদ্ধতিটি : এইভাবে আপনি মানটি পরিবর্তন করবেন।

আল্টোহাগ এটি সেই ক্ষেত্রে সীমাবদ্ধ যেখানে মানগুলি স্ট্রিং হয় এবং তাই প্রশ্নের পুরোপুরি উত্তর দেয় না, আমি ভেবেছিলাম এটি কারও পক্ষে কার্যকর হতে পারে।


1
new_hash = old_hash.merge(old_hash) do |_key, value, _value|
             value.upcase
           end

# old_hash = {"a" => "b", "c" => "d"}
# new_hash = {"a" => "B", "c" => "D"}

এটা কি দক্ষ?
ioquatix
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.