অ্যারে টু হ্যাশ রুবি


192

ঠিক আছে তাই এখানে চুক্তি, আমি এর সমাধান খুঁজতে আমি যুগ যুগ ধরে গুগল করছি এবং সেখানে অনেকগুলি থাকার পরেও তারা যে কাজটি আমি সন্ধান করছি তাতে করে বলে মনে হয় না।

মূলত আমার এ ধরণের একটি অ্যারে রয়েছে

["item 1", "item 2", "item 3", "item 4"] 

আমি এটি একটি হ্যাশ রূপান্তর করতে চাই তাই এটি দেখতে দেখতে

{ "item 1" => "item 2", "item 3" => "item 4" }

অর্থাত্ 'এমনকি' সূচকগুলিতে থাকা আইটেমগুলি কী এবং 'বিজোড়' সূচীর আইটেমগুলির মান।

কোনও ধারণা কীভাবে এটি পরিষ্কারভাবে করবেন? আমি মনে করি একটি নিষ্ঠুর বল পদ্ধতিটি হ'ল সমস্ত ইন্ডেক্সকে একটি পৃথক অ্যারেতে বের করে দেওয়া এবং তারপরে মানগুলি যুক্ত করতে তাদের চারপাশে লুপ করা।

উত্তর:


357
a = ["item 1", "item 2", "item 3", "item 4"]
h = Hash[*a] # => { "item 1" => "item 2", "item 3" => "item 4" }

এটাই. *বলা হয় splat অপারেটর।

@ মাইক লুইস প্রতি একটি সতর্কতা (মন্তব্যগুলিতে): "এটির সাথে খুব সাবধানতা অবলম্বন করুন। রুবি স্ট্যাকের উপর স্প্ল্যাটগুলি প্রসারিত করে।

সুতরাং, বেশিরভাগ সাধারণ ব্যবহারের ক্ষেত্রে এই পদ্ধতিটি দুর্দান্ত, তবে আপনি যদি প্রচুর ডেটাতে রূপান্তর করতে চান তবে একটি আলাদা পদ্ধতি ব্যবহার করুন। উদাহরণস্বরূপ, @ asukasz Niemier (এছাড়াও মন্তব্যে) বড় ডেটা সেটগুলির জন্য এই পদ্ধতিটি সরবরাহ করে:

h = Hash[a.each_slice(2).to_a]

10
@tester, *এটিকে স্প্ল্যাট অপারেটর বলা হয় । এটি একটি অ্যারে নেয় এবং এটিকে আইটেমের আক্ষরিক তালিকায় রূপান্তর করে। সুতরাং *[1,2,3,4]=> 1, 2, 3, 4। এই উদাহরণে, উপরেরটি করণ সমান Hash["item 1", "item 2", "item 3", "item 4"]। এবং Hashএমন একটি []পদ্ধতি রয়েছে যা আর্গুমেন্টের একটি তালিকা গ্রহণ করে (এমনকি সূচি কী এবং বিজোড় সূচকগুলির মান তৈরি করে), তবে Hash[]কোনও অ্যারে গ্রহণ করে না, তাই আমরা অ্যারেটি ব্যবহার করে স্প্লিট করি *
বেন লি

15
এই সম্পর্কে খুব সতর্কতা অবলম্বন করুন। রুবি স্ট্যাকের স্প্ল্যাটগুলি প্রসারিত করে। আপনি যদি বড় ডেটাসেট দিয়ে এটি করেন তবে আপনার স্ট্যাকটি ফুটিয়ে তোলার প্রত্যাশা করুন।
মাইক লুইস

9
বড় ডেটা টেবিলগুলিতে আপনি ব্যবহার করতে পারেন Hash[a.each_slice(2).to_a]
হাউলেথ

4
"আপনার স্ট্যাক ফুটিয়ে তুলুন" এর অর্থ কী?
কেভিন

6
কেভিন, স্ট্যাকটি মেমরির একটি ছোট ক্ষেত্র ব্যবহার করে যা প্রোগ্রামটি নির্দিষ্ট কিছু ক্রিয়াকলাপের জন্য বরাদ্দ করে এবং সংরক্ষণ করে। সর্বাধিক সাধারণভাবে, এটি এখনও পর্যন্ত বলা যাওয়া পদ্ধতিগুলির স্ট্যাক রাখতে ব্যবহৃত হয়। এটি স্ট্যাক ট্রেস শব্দের উত্স এবং এ কারণেই একটি অসীম পুনরাবৃত্তি পদ্ধতি স্ট্যাকের ওভারফ্লো করতে পারে । এই উত্তরের পদ্ধতিটি স্ট্যাকটিও ব্যবহার করে, তবে যেহেতু স্ট্যাকটি কেবল মেমরির একটি ক্ষুদ্রতর ক্ষেত্র, আপনি যদি এই পদ্ধতিটি বড় অ্যারে দিয়ে চেষ্টা করেন তবে এটি স্ট্যাকটি পূরণ করবে এবং ত্রুটির কারণ হবে (একই রেখাগুলিতে ত্রুটি রয়েছে একটি স্ট্যাক ওভারফ্লো)।
বেন লি

103

রুবি ২.১.০ to_hঅ্যারেতে এমন একটি পদ্ধতি প্রবর্তন করেছে যা আপনার মূল অ্যারেটিতে কী-মান জোড়ার অ্যারে সমন্বিত হলে আপনার প্রয়োজনটি হয়: http://www.ruby-doc.org/core-2.1.0/Array.html#method -i-to_h

[[:foo, :bar], [1, 2]].to_h
# => {:foo => :bar, 1 => 2}

1
সুন্দর! এখানে অন্যান্য সমাধানগুলির চেয়ে অনেক ভাল better
ডেনিস

3
পূর্বের ২.১.০ রুবি সংস্করণগুলির জন্য, আপনি হ্যাশ :: []] পদ্ধতিটি একই ধরণের ফলাফল পেতে ব্যবহার করতে পারেন, যতক্ষণ না আপনার কাছে নেস্টেড অ্যারের জোড়া থাকে। সুতরাং a = [[: ফু,: 1], [বার, ২]] --- হ্যাশ [এ] => {:
ফু

@ আফডেভ, সত্যই, ধন্যবাদ আপনি সঠিক (ছোটখাটো টাইপগুলি উপেক্ষা করার সময়: barএকটি প্রতীক :2হওয়া দরকার , এবং প্রতীকটি একটি পূর্ণসংখ্যা হওয়া উচিত So সুতরাং, আপনার অভিব্যক্তি সংশোধন করা হয়েছে a = [[:foo, 1], [:bar, 2]])।
জোহেম শুলেনক্লোপার

28

Hash.[]অ্যারেতে মানগুলি ব্যবহার করুন । উদাহরণ স্বরূপ:

arr = [1,2,3,4]
Hash[*arr] #=> gives {1 => 2, 3 => 4}

1
[* আরআর] এর অর্থ কী?
অ্যালান করোমানো

1
@ মারিয়াস: আর্গুমেন্টের তালিকায় *arrরূপান্তরিত arrহয়, সুতরাং এটি []হ্যাশের পদ্ধতিটিকে আর্টের বিষয়বস্তু দিয়ে আর্গুমেন্ট হিসাবে কল করছে।
চক

26

বা আপনার কাছে [key, value]অ্যারেগুলির একটি অ্যারে থাকলে আপনি এটি করতে পারেন:

[[1, 2], [3, 4]].inject({}) do |r, s|
  r.merge!({s[0] => s[1]})
end # => { 1 => 2, 3 => 4 }

2
আপনি উত্তর প্রশ্নের সাথে সম্পর্কিত নন এবং আপনার ক্ষেত্রে এটি একই ব্যবহার করা এখনও অনেক সহজHash[*arr]
Yossi

2
নাঃ। এটা ফিরে আসত { [1, 2] => [3, 4] }। এবং যেহেতু প্রশ্নের শিরোনামটি "অ্যারে থেকে হ্যাশ" বলে এবং অন্তর্নির্মিত "হ্যাশ থেকে অ্যারে" পদ্ধতিটি করে: { 1 => 2, 3 => 4}.to_a # => [[1, 2], [3, 4]]আমি ভেবেছিলাম যে বিল্ট-ইন "হ্যাশ থেকে অ্যারে" পদ্ধতির বিপরীতমুখী হওয়ার চেষ্টা করে একেরও বেশি এখানে শেষ হতে পারে। আসলে, এভাবেই আমি এখানেই শেষ করেছি ended
এরিক এসকোবেডো

1
দুঃখিত, আমি একটি অতিরিক্ত নক্ষত্র যুক্ত করেছি। Hash[arr]আপনার জন্য কাজ করবে।
ইয়াসি

9
আইএমএইচও এর আরও ভাল সমাধান: হ্যাশ [* অ্যারে.ফ্ল্যাটেন (1)]
অতিথি

2
ইয়োসি: মৃতদের জীবিত করার জন্য দুঃখিত, তবে তার উত্তর নিয়ে আরও একটি বড় সমস্যা রয়েছে এবং তা হচ্ছে #injectপদ্ধতির ব্যবহার । সঙ্গে #merge!, #each_with_objectব্যবহার করা উচিত ছিল। যদি #injectজোর দেওয়া হয়, #mergeবরং #merge!ব্যবহার করা উচিত ছিল।
বরিস স্ট্যাটনিকিকি

12

এটি গুগল করার সময় আমি এটির সন্ধান করছিলাম:

[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}


আপনি ব্যবহার করতে চান না merge, এটি প্রতি লুপ পুনরাবৃত্তির জন্য একটি নতুন হ্যাশ তৈরি করে এবং বাতিল করে দেয় এবং খুব ধীর গতির। যদি এর পরিবর্তে আপনি একটি অ্যারে হ্যাশ চেষ্টা [{a:1},{b:2}].reduce({}, :merge!)করে দেখেন - এটি সবকিছুকে একই (নতুন) হ্যাশে মিশ্রিত করে।

ধন্যবাদ, আমিও এটাই চেয়েছিলাম! :)
থানাসিস পেটসাস

আপনিও করতে পারেন.reduce(&:merge!)
বেন লি

1
[{a: 1}, {b: 2}].reduce(&:merge!)মূল্যায়ন{:a=>1, :b=>2}
বেন লি

এটি কাজ করে কারণ ইনজেক্ট / হ্রাস একটি বৈশিষ্ট্য রয়েছে যেখানে আপনি আর্গুমেন্টটি বাদ দিতে পারেন, সেক্ষেত্রে এটি ইনপুট আর্গুমেন্ট হিসাবে কাজ করতে অ্যারের প্রথম যুক্তি এবং বাকী অ্যারে হিসাবে অ্যারের ব্যবহার করে। প্রতীক-টু-প্রোক সহ এটি একত্রিত করুন এবং আপনি এই সংক্ষিপ্ত নির্মাণটি পাবেন। অন্য কথায় [{a: 1}, {b: 2}].reduce(&:merge!)একই হিসাবে [{a: 1}, {b: 2}].reduce { |m, x| m.merge(x) }একই হিসাবে হয় [{b: 2}].reduce({a: 1}) { |m, x| m.merge(x) }
বেন লি

10

Enumeratorঅন্তর্ভুক্ত Enumerable। যেহেতু 2.1, Enumerableএছাড়াও একটি পদ্ধতি আছে #to_h। এজন্যই, আমরা লিখতে পারি: -

a = ["item 1", "item 2", "item 3", "item 4"]
a.each_slice(2).to_h
# => {"item 1"=>"item 2", "item 3"=>"item 4"}

কারণ #each_sliceব্লক ছাড়াই আমাদের দেয় Enumeratorএবং উপরের ব্যাখ্যা অনুসারে আমরা বস্তুটিতে #to_hপদ্ধতিটি কল করতে পারি Enumerator


7

আপনি একক অ্যারের জন্য এটির মতো চেষ্টা করতে পারেন

irb(main):019:0> a = ["item 1", "item 2", "item 3", "item 4"]
  => ["item 1", "item 2", "item 3", "item 4"]
irb(main):020:0> Hash[*a]
  => {"item 1"=>"item 2", "item 3"=>"item 4"}

অ্যারের অ্যারের জন্য

irb(main):022:0> a = [[1, 2], [3, 4]]
  => [[1, 2], [3, 4]]
irb(main):023:0> Hash[*a.flatten]
  => {1=>2, 3=>4}

6
a = ["item 1", "item 2", "item 3", "item 4"]
Hash[ a.each_slice( 2 ).map { |e| e } ]

বা, যদি আপনি ঘৃণা করেন Hash[ ... ]:

a.each_slice( 2 ).each_with_object Hash.new do |(k, v), h| h[k] = v end

বা, আপনি যদি ভাঙ্গা ক্রিয়ামূলক প্রোগ্রামিংয়ের অলস ভক্ত হন:

h = a.lazy.each_slice( 2 ).tap { |a|
  break Hash.new { |h, k| h[k] = a.find { |e, _| e == k }[1] }
}
#=> {}
h["item 1"] #=> "item 2"
h["item 3"] #=> "item 4"

আপনি যদি সম্পূর্ণ ঘৃণা না করেন Hash[ ... ]তবে এটি শৃঙ্খলাবদ্ধ পদ্ধতি হিসাবে ব্যবহার করতে চান (যেমন আপনি এটি করতে পারেন to_h) আপনি বরিসের পরামর্শগুলি একত্রিত করতে পারেন এবং লিখতে পারেন:arr.each_slice( 2 ).map { |e| e }.tap { |a| break Hash[a] }
বি-স্টুডিওগুলি

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

1

সমস্ত উত্তর ধরে নেওয়া শুরু করা অ্যারেটি অনন্য। ওপি সদৃশ এন্ট্রি দ্বারা অ্যারেগুলি কীভাবে পরিচালনা করতে হবে তা নির্দিষ্ট করে নি, যার ফলে সদৃশ কীগুলির ফলাফল হয়।

এদিকে তাকান:

a = ["item 1", "item 2", "item 3", "item 4", "item 1", "item 5"]

item 1 => item 2বিজ জয়ী হওয়ার কারণে আপনি এই জুটিটি হারাবেন item 1 => item 5:

Hash[*a]
=> {"item 1"=>"item 5", "item 3"=>"item 4"}

সহ সমস্ত পদ্ধতি reduce(&:merge!)একই অপসারণের ফলাফল ।

এটি এমনটি হতে পারে যা আপনি প্রত্যাশা করেন ঠিক তেমনই। তবে অন্যান্য ক্ষেত্রে, আপনি সম্ভবত Arrayপরিবর্তে মান সহ ফলাফল পেতে চান :

{"item 1"=>["item 2", "item 5"], "item 3"=>["item 4"]}

নিষ্পাপ উপায় হ'ল একটি সহায়ক ভেরিয়েবল তৈরি করা, একটি হ্যাশ যার ডিফল্ট মান রয়েছে এবং তারপরে একটি লুপটি পূরণ করুন:

result = Hash.new {|hash, k| hash[k] = [] } # Hash.new with block defines unique defaults.
a.each_slice(2) {|k,v| result[k] << v }
a
=> {"item 1"=>["item 2", "item 5"], "item 3"=>["item 4"]}

উপরের এক লাইনে ব্যবহার করা assocএবং করা সম্ভব হতে পারে reduceতবে যুক্তি করা এবং পড়া খুব শক্ত হয়ে যায়।

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