রুবির একটি হ্যাশের প্রতিটি মান পরিবর্তন করা


170

আমি হ্যাশের প্রতিটি মান পরিবর্তন করতে চাই যাতে এর আগে এবং পরে '%' যুক্ত হয়

{ :a=>'a' , :b=>'b' }

পরিবর্তন করতে হবে

{ :a=>'%a%' , :b=>'%b%' }

এটি করার সর্বোত্তম উপায় কী?


1
আপনি যদি মূল স্ট্রিং অবজেক্টগুলিকে রূপান্তর করতে চান তবে কেবল আসলটির রূপান্তর করতে চান বা কিছুই পরিবর্তন করতে চান না দয়া করে স্পষ্ট করুন।
ফ্রেগজ

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

তবে তবুও অ্যাপ্রোচটি দুর্দান্ত ছিল
রিভার্স ফ্লিক

উত্তর:


178

যদি আপনি প্রকৃত স্ট্রিংগুলি নিজের জায়গায় পরিবর্তিত করতে চান (সম্ভবত এবং একই স্ট্রিং অবজেক্টের অন্যান্য রেফারেন্সগুলিকে আকাঙ্ক্ষিতভাবে প্রভাবিত করুন):

# Two ways to achieve the same result (any Ruby version)
my_hash.each{ |_,str| str.gsub! /^|$/, '%' }
my_hash.each{ |_,str| str.replace "%#{str}%" }

আপনি যদি হ্যাশটি পরিবর্তিত করতে চান তবে আপনি স্ট্রিংগুলিকে প্রভাবিত করতে চান না (আপনি এটি নতুন স্ট্রিংগুলি পেতে চান):

# Two ways to achieve the same result (any Ruby version)
my_hash.each{ |key,str| my_hash[key] = "%#{str}%" }
my_hash.inject(my_hash){ |h,(k,str)| h[k]="%#{str}%"; h }

আপনি যদি একটি নতুন হ্যাশ চান:

# Ruby 1.8.6+
new_hash = Hash[*my_hash.map{|k,str| [k,"%#{str}%"] }.flatten]

# Ruby 1.8.7+
new_hash = Hash[my_hash.map{|k,str| [k,"%#{str}%"] } ]

1
@ অ্যান্ড্রু মার্শাল ঠিক আছেন, ধন্যবাদ রুবি ১.৮-তে, Hash.[]অ্যারে জোড়গুলির একটি অ্যারে গ্রহণ করে না, এটির জন্য সরাসরি সংখ্যার যুক্তিগুলির একটি বৃহত পরিমাণ প্রয়োজন (তাই সামনে স্প্ল্যাট আপ)।
ফ্রোগজ

2
প্রকৃতপক্ষে, হ্যাশ। [কী_ভালিউ_পেজ] ১.৮..7 সালে প্রবর্তিত হয়েছিল, সুতরাং কেবল রুবি ১.৮.। এর স্প্ল্যাট এবং চ্যাপ্টের প্রয়োজন নেই।
মার্ক-আন্দ্রে লাফোর্টুন

2
@ অপাজো ব্লকটিতে Hash#eachকী এবং মান উভয়ই দেয়। এই ক্ষেত্রে, আমি কীটির বিষয়ে চিন্তা করিনি, এবং তাই আমি এটির কোনও কার্যকর নামকরণ করি নি। পরিবর্তনশীল নামগুলি একটি আন্ডারস্কোর দিয়ে শুরু হতে পারে এবং বাস্তবে কেবল একটি আন্ডারস্কোর হতে পারে । এটি করার কোনও কার্যকারিতা সুবিধা নেই, এটি কেবল একটি সূক্ষ্ম স্ব-ডকুমেন্টিং নোট যে আমি প্রথম ব্লকের মানটি দিয়ে কিছুই করছি না।
ফ্রোগজ

1
আমার মনে হয় আপনার অর্থ my_hash.inject(my_hash){ |h,(k,str)| h[k]="%#{str}%"; h }, ব্লক থেকে হ্যাশটি ফিরিয়ে দিতে হবে
aceofspades

1
পর্যায়ক্রমে, আপনি প্রতিটি_মূল্য পদ্ধতিটি ব্যবহার করতে পারেন যা অব্যবহৃত কী মানটির জন্য আন্ডারস্কোর ব্যবহার করার চেয়ে বোঝা সহজ।
স্ট্র্যান্ড ম্যাককচেন

266

রুবি ২.১ এবং এর চেয়ে বেশি আপনি করতে পারেন

{ a: 'a', b: 'b' }.map { |k, str| [k, "%#{str}%"] }.to_h

5
ধন্যবাদ, আসলে আমি যা খুঁজছিলাম। আপনি কেন এতটা উজ্জীবিত হচ্ছেন না জানি না।

7
এটি অত্যন্ত ধীর এবং খুব ক্ষুধার্ত RAM ইনপুট হ্যাশটি পুনরায় পুনরুক্ত করা হয় নেস্টেড অ্যারেগুলির একটি মধ্যবর্তী সেট তৈরি করার জন্য যা পরে একটি নতুন হ্যাসে রূপান্তরিত হয়। র‌্যাম পিকের ব্যবহার উপেক্ষা করে রান চালানোর সময়টি আরও খারাপ - একই উত্তর সংখ্যাগুলির তুলনায় 1.5 সেকেন্ডের তুলনায় অন্য উত্তরগুলিতে 2.5-এর পরিবর্তে স্থান পরিবর্তন সমাধানের তুলনায় বেঞ্চমার্ক। যেহেতু রুবি তুলনামূলকভাবে ধীর ভাষা, তাই ধীর ভাষার ধীরে ধীরে বিটগুলি এড়িয়ে চলা অনেক বোঝায় :-)
অ্যান্ড্রু হজকিনসন

2
@ অ্যান্ড্রুহডজকিনসন সাধারণভাবে আমি সম্মত হয়েছি এবং রানটাইম পারফরম্যান্সের দিকে মনোযোগ না দেওয়ার পক্ষে পরামর্শ দিচ্ছি না, এই সমস্ত পারফরম্যান্সের ক্ষতিগুলি ট্র্যাক না করে কি রুবীর "বিকাশকারী উত্পাদনশীলতা প্রথম" দর্শনের বিরুদ্ধে যায় না? আমার ধারণা এটি আপনার কাছে কমেন্টের মত কম, এবং রুবি ব্যবহার করে শেষের প্যারাডক্সের উপর সাধারণ মন্তব্য বেশি।
এলসুরুদো

4
জঞ্জালটি হ'ল: ভাল, আমরা রুবি ব্যবহারের সিদ্ধান্ত নেওয়ার ক্ষেত্রে ইতিমধ্যে কর্মক্ষমতা ছেড়ে দিচ্ছি, তবে "এই অন্যান্য সামান্য" কী পার্থক্য করবে? এটি পিচ্ছিল opeাল, তাই না? রেকর্ডের জন্য, আমি এই সমাধানটি পাঠযোগ্যতার দৃষ্টিকোণ থেকে গ্রহণযোগ্য উত্তরের চেয়ে পছন্দ করি।
এলসুরুদো

1
আপনি রুবি 2.4+ ব্যবহার করেন, তাহলে এটা এমনকি ব্যবহার করা আরো সহজ #transform_values!sschmeck (দ্বারা সরু আউট হিসাবে stackoverflow.com/a/41508214/6451879 )।
ফিন

127

রুবি ২.৪ পদ্ধতিটি চালু করেছে Hash#transform_values!, যা আপনি ব্যবহার করতে পারেন।

{ :a=>'a' , :b=>'b' }.transform_values! { |v| "%#{v}%" }
# => {:a=>"%a%", :b=>"%b%"} 

ঠিক আমি খুঁজছেন ছিল কি!
দোলেভ

4
অবশ্যই আছে Hash#transform_values(ঠুং ঠুং শব্দ ছাড়া), যা রিসিভারটি পরিবর্তন করে না। অন্যথায় দুর্দান্ত উত্তর, ধন্যবাদ!
আইজিএল

1
এটি সত্যিই আমার ব্যবহারগুলি :-preduce
iGEL

86

হ্যাশের মানগুলিকে পরিবর্তিত করার সর্বোত্তম উপায় হ'ল

hash.update(hash){ |_,v| "%#{v}%" }

কম কোড এবং পরিষ্কার উদ্দেশ্য। আরও দ্রুত কারণ কোনও নতুন অবজেক্টকে যে মানগুলি পরিবর্তিত করতে হবে তার বাইরে বরাদ্দ দেওয়া হয়নি।


ঠিক সত্য নয়: নতুন স্ট্রিং বরাদ্দ করা হয়। তবুও, একটি আকর্ষণীয় সমাধান যা কার্যকর। +1
ফ্রোগজ

@ ফ্রোগজ ভালো পয়েন্ট; আমি উত্তর আপডেট। সাধারণভাবে মূল্য বরাদ্দ এড়ানো যায় না কারণ সমস্ত মান রূপান্তর যেমন মিউটর হিসাবে প্রকাশ করা যায় না gsub!
সিম

3
আমার উত্তর হিসাবে একই কিন্তু অন্য প্রতিশব্দ সঙ্গে, আমি সম্মত যে এর updateচেয়ে ভাল উদ্দেশ্য জানাতে merge!। আমি মনে করি এটিই সেরা উত্তর।

1
আপনি যদি kব্যবহার না করেন তবে _পরিবর্তে ব্যবহার করুন।
সেক্রেট

28

কিছুটা আরও পঠনযোগ্য, mapএটি একক-উপাদান হ্যাশগুলির একটি অ্যারে এবং এটির reduceসাথেmerge

the_hash.map{ |key,value| {key => "%#{value}%"} }.reduce(:merge)

2
পরিস্কার ব্যবহার করতেHash[the_hash.map { |key,value| [key, "%#{value}%"] }]
meagar

মানগুলি আপডেট করার এটি একটি অত্যন্ত অযোগ্য উপায়। প্রতিটি মান জোড়ার জন্য এটি প্রথমে একটি জোড় তৈরি করে Array(এর জন্য map) তারপর ক Hash। তারপরে হ্রাস অপারেশনের প্রতিটি পদক্ষেপ "মেমো "টিকে নকল করবে Hashএবং এতে নতুন কী-মান জুটি যুক্ত করবে। অন্তত ব্যবহার এ :merge!মধ্যে reduceচূড়ান্ত সংশোধন করার Hashজায়গায়। এবং শেষ অবধি, আপনি বিদ্যমান বস্তুর মানগুলি পরিবর্তন করছেন না বরং একটি নতুন অবজেক্ট তৈরি করছেন, যা প্রশ্নটি জিজ্ঞাসা করে না what
সিম

এটি খালি nilথাকলে ফিরে আসেthe_hash
DNNX

18

এই টাস্কের জন্য একটি নতুন 'রেল ওয়ে' পদ্ধতি রয়েছে :) http://api.rubyonrails.org/classes/Hash.html#method-i-transfor_values


8
এছাড়াও রুবি ২.৪.০++ রয়েছে Hash#transform_values। এখন থেকে এই পথ চলতে হবে।
অ্যামিবে

1
সংক্ষেপে, রেল 5+ বা রুবি ২.৪++ এর জন্য উপলভ্য
সিরিল ডুচন-ডরিস 20'17

+ .০
++

16

একটি পদ্ধতি যা মূলটির সাথে পার্শ্ব প্রতিক্রিয়াগুলি প্রবর্তন করে না:

h = {:a => 'a', :b => 'b'}
h2 = Hash[h.map {|k,v| [k, '%' + v + '%']}]

হ্যাশ # মানচিত্রটি একটি আকর্ষণীয় পঠন হতে পারে কারণ এটি ব্যাখ্যা করেHash.map হ্যাশ ফেরত আসে না (যার কারণে জোড়গুলির ফলে অ্যারেটি [key,value]নতুন হ্যাশে রূপান্তরিত হয়) এবং একই সাধারণ প্যাটার্নের বিকল্প পন্থা সরবরাহ করে।

শুভ কোডিং।

[অস্বীকৃতি: Hash.mapরুবি ২.x তে শব্দার্থবিজ্ঞানের পরিবর্তন হয়েছে কিনা তা আমি নিশ্চিত নই ]


7
ম্যাটজ এমনকি Hash.mapরুবি ২.x-তে শব্দার্থবিজ্ঞানের পরিবর্তন কিনা তাও জানেন ?
অ্যান্ড্রু গ্রিম

1
হ্যাশ # [] পদ্ধতিটি এত কার্যকর, তবে খুব কুশ্রী। অ্যারেগুলিকে একইভাবে হ্যাশে রূপান্তর করার কোনও প্রাকৃতিক পদ্ধতি আছে?
মার্টিজন

15
my_hash.each do |key, value|
  my_hash[key] = "%#{value}%"
end

আমি পার্শ্ব প্রতিক্রিয়া পছন্দ করি না, তবে পদ্ধতির জন্য +1 :) এখানে each_with_objectরুবি ১.৯ (আইআইআরসি) রয়েছে যা সরাসরি নাম অ্যাক্সেস করার প্রয়োজন এড়িয়ে যায় এবং Map#mergeএটি কাজও করতে পারে। কীভাবে জটিল বিশদগুলি পৃথক হয় তা নিশ্চিত নয়।

1
প্রাথমিক হ্যাশটি সংশোধিত হয়েছে - আচরণটি প্রত্যাশিত থাকলে এটি ঠিক আছে তবে "ভুলে গেলে" সূক্ষ্ম সমস্যা তৈরি করতে পারে। আমি বস্তুর পরিবর্তনকে হ্রাস করতে পছন্দ করি তবে এটি সর্বদা ব্যবহারিক নাও হতে পারে। (রুবি সম্ভবত "পার্শ্ব-প্রতিক্রিয়াহীন" ভাষা ;-)

8

Hash.merge! সবচেয়ে পরিষ্কার সমাধান

o = { a: 'a', b: 'b' }
o.merge!(o) { |key, value| "%#{ value }%" }

puts o.inspect
> { :a => "%a%", :b => "%b%" }

@ মিশিগেলদেমে আমি দুঃখিত, আমি এটির যথেষ্ট পরীক্ষা করিনি didn't আপনি সঠিক, ব্লকের দুটি পরামিতি নেওয়া দরকার। সংশোধন।

5

আরএসপেক দিয়ে এটির মতো পরীক্ষার পরে:

describe Hash do
  describe :map_values do
    it 'should map the values' do
      expect({:a => 2, :b => 3}.map_values { |x| x ** 2 }).to eq({:a => 4, :b => 9})
    end
  end
end

আপনি নিম্নরূপে হ্যাশ # মানচিত্র_ মানগুলি প্রয়োগ করতে পারেন:

class Hash
  def map_values
    Hash[map { |k, v| [k, yield(v)] }]
  end
end

ফাংশনটি এভাবে ব্যবহার করা যেতে পারে:

{:a=>'a' , :b=>'b'}.map_values { |v| "%#{v}%" }
# {:a=>"%a%", :b=>"%b%"}

1

যদি আপনি কৌতূহলী হন তবে কোন স্থানের রূপটি এখানে দ্রুত হয় তা হল:

Calculating -------------------------------------
inplace transform_values! 1.265k  0.7%) i/s -      6.426k in   5.080305s
      inplace update      1.300k  2.7%) i/s -      6.579k in   5.065925s
  inplace map reduce    281.367   1.1%) i/s -      1.431k in   5.086477s
      inplace merge!      1.305k  0.4%) i/s -      6.630k in   5.080751s
        inplace each      1.073k  0.7%) i/s -      5.457k in   5.084044s
      inplace inject    697.178   0.9%) i/s -      3.519k in   5.047857s
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.