রুবিতে একটি অ্যারের মাধ্যমে পুনরাবৃত্তি করার "ডান" উপায় কী?


341

পিএইচপি, সমস্ত যুদ্ধের জন্য, এই গণনায় বেশ ভাল is অ্যারে এবং হ্যাশের মধ্যে কোনও পার্থক্য নেই (সম্ভবত আমি নির্বোধ, তবে এটি আমার কাছে স্পষ্টতই সঠিক বলে মনে হচ্ছে), এবং আপনি কেবলমাত্র এটির মধ্য দিয়ে পুনরাবৃত্তি করতে পারেন

foreach (array/hash as $key => $value)

রুবিতে এই ধরণের কাজটি করার অনেকগুলি উপায় রয়েছে:

array.length.times do |i|
end

array.each

array.each_index

for i in array

হ্যাশগুলি আরও বোধগম্য হয়, যেহেতু আমি সবসময় ব্যবহার করি

hash.each do |key, value|

আমি কেন অ্যারে করতে পারি না? আমি যদি কেবল একটি পদ্ধতি মনে করতে চাই তবে আমার ধারণা আমি ব্যবহার করতে পারি each_index(যেহেতু এটি সূচক এবং মান উভয় উপলব্ধ করে) তবে এটি array[index]কেবল ন্যায়বিচারের পরিবর্তে করতে হবে তা বিরক্তিকর value


ওহ ঠিক আছে, আমি ভুলে গিয়েছিলাম array.each_with_index। যাইহোক, এই এক কারণ এটি যায় |value, key|এবং hash.eachযায় |key, value|! এটা কি উন্মাদ নয়?


1
আমি array#each_with_indexব্যবহারগুলি অনুমান করি |value, key|কারণ পদ্ধতির নামটি অর্ডারকে বোঝায়, যেখানে hash#eachক্রমটি hash[key] = valueসিনট্যাক্সের অনুকরণের জন্য ব্যবহৃত হয়েছে ?
বেঞ্জিনিয়ার

উত্তর:


560

এটি সমস্ত উপাদানগুলির মাধ্যমে পুনরাবৃত্তি করবে:

array = [1, 2, 3, 4, 5, 6]
array.each { |x| puts x }

ছাপে:

1
2
3
4
5
6

এটি আপনাকে মান এবং সূচক দেওয়ার জন্য সমস্ত উপাদানগুলির মাধ্যমে পুনরাবৃত্তি করবে:

array = ["A", "B", "C"]
array.each_with_index {|val, index| puts "#{val} => #{index}" }

ছাপে:

A => 0
B => 1
C => 2

আপনি কোনটি সন্ধান করছেন তা আপনার প্রশ্ন থেকে আমি নিশ্চিত নই।


1
অফ-টপিক আমি রুবি ১.৯ তে অ্যারে -তে প্রতিটি_ইথ_ইন্ডেক্সটি খুঁজে পাচ্ছি না
ক্যান্টগেটানিক

19
@ ক্যান্টগেটানিক: অ্যারে ক্লাসে এনিউমারেবল মডিউল রয়েছে যা এই পদ্ধতিতে রয়েছে।
xuinkrbin।

88

আমি মনে করি সঠিক উপায় নেই। পুনরাবৃত্তি করার বিভিন্ন উপায় রয়েছে এবং প্রত্যেকটির নিজস্ব কুলুঙ্গি রয়েছে।

  • each অনেকগুলি ব্যবহারের জন্য যথেষ্ট, যেহেতু আমি প্রায়শই সূচকের বিষয়ে চিন্তা করি না।
  • each_ with _index প্রতিটি হ্যাশ # এর মতো কাজ করে - আপনি মান এবং সূচক পান।
  • each_index- শুধু সূচি। আমি এটি প্রায়শই ব্যবহার করি না। "দৈর্ঘ্য.টাইমস" এর সমান।
  • map পুনরাবৃত্তি করার অন্য উপায়, আপনি যখন একটি অ্যারেটিকে অন্যটিতে রূপান্তর করতে চান তখন দরকারী।
  • select আপনি যখন কোনও উপসেট চয়ন করতে চান তখন ব্যবহারের জন্য পুনরাবৃত্তকারী।
  • inject অঙ্ক বা পণ্য উত্পাদন, বা একক ফলাফল সংগ্রহের জন্য দরকারী।

এটি মনে রাখা অনেকটা মনে হতে পারে তবে চিন্তা করবেন না, আপনি তাদের সমস্ত কিছু না জেনেও পেতে পারেন। তবে আপনি বিভিন্ন পদ্ধতি শিখতে এবং ব্যবহার করতে শুরু করার সাথে সাথে আপনার কোডটি আরও পরিষ্কার এবং পরিষ্কার হয়ে যাবে এবং আপনি রুবি আয়ত্তের পথে যাবেন।


দুর্দান্ত উত্তর! আমি # রিজেক্টের মতো বিপরীত এবং # কলকের মতো উপকরণ উল্লেখ করতে চাই।
এমিলি তুই চি

60

আমি বলছি না Array-> |value,index|এবং Hash-> |key,value|উন্মাদ নয় (হোরেস লয়েবের মন্তব্য দেখুন), তবে আমি বলছি যে এই ব্যবস্থাটি প্রত্যাশা করার একটি বুদ্ধিমান উপায় আছে।

যখন আমি অ্যারেগুলি নিয়ে কাজ করি, তখন আমি অ্যারের উপাদানগুলিতে মনোনিবেশ করি (সূচকটি ট্রানজিস্ট্রি হওয়ায় সূচকে নয়)। পদ্ধতিটি প্রতিটি সূচক সহ প্রতিটি, অর্থাৎ প্রতিটি + সূচক, বা | প্রতিটি, সূচক |, বা|value,index| । এটি সূচকটিকে alচ্ছিক যুক্তি হিসাবে দেখা হচ্ছে, যেমন: মান value | মান, সূচক = শূন্যের সমতুল্য যা | মান, সূচক | এর সাথে সামঞ্জস্যপূর্ণ।

আমি যখন হ্যাশগুলি নিয়ে কাজ করি তখন আমি প্রায়শই মানগুলির চেয়ে কীগুলিতে বেশি মনোনিবেশ করি এবং আমি সাধারণত key => valueবা সেই সাথে এই ক্রমে কীগুলি এবং মানগুলি নিয়ে কাজ করছি hash[key] = value

আপনি যদি হাঁস-টাইপিং করতে চান, তবে ব্রেন্ট লংবোরো যেভাবে দেখিয়েছেন তা স্পষ্টভাবে একটি সংজ্ঞায়িত পদ্ধতি ব্যবহার করুন বা ম্যাকহাকিন্সের মতো একটি অন্তর্নিহিত পদ্ধতি ব্যবহার করুন।

রুবি প্রোগ্রামার অনুসারে ভাষা সংযোজন করার বিষয়ে, ভাষা অনুসারে প্রোগ্রামারকে সংযুক্ত করার বিষয়ে নয়। এই কারণেই অনেকগুলি উপায় রয়েছে। কিছু চিন্তা করার অনেক উপায় আছে। রুবিতে, আপনি সবচেয়ে কাছেরটি চয়ন করেন এবং বাকী কোডটি সাধারণত খুব ঝরঝরে এবং সংক্ষিপ্তভাবে আসে।

মূল প্রশ্ন হিসাবে, "রুবিতে অ্যারের মাধ্যমে পুনরাবৃত্তি করার" সঠিক "উপায়টি কী?", ভাল, আমি মনে করি মূল উপায়টি (অর্থাত্ শক্তিশালী সিনট্যাকটিক চিনি বা বস্তু কেন্দ্রিক শক্তি ছাড়াই) করণীয়:

for index in 0 ... array.size
  puts "array[#{index}] = #{array[index].inspect}"
end

তবে রুবি শক্তিশালী সিনট্যাকটিক চিনি এবং অবজেক্ট ওরিয়েন্টেড পাওয়ার সম্পর্কে, তবে যাইহোক এখানে হ্যাশগুলির সমতুল্য, এবং কীগুলি অর্ডার করা যায় বা না:

for key in hash.keys.sort
  puts "hash[#{key.inspect}] = #{hash[key].inspect}"
end

সুতরাং, আমার উত্তরটি হ'ল, "রুবিতে একটি অ্যারের মাধ্যমে পুনরাবৃত্তি করার" সঠিক "উপায়টি আপনার উপর নির্ভর করে (যেমন প্রোগ্রামার বা প্রোগ্রামিং টিম) এবং প্রকল্প" রুবি আরও ভাল প্রোগ্রামার আরও ভাল পছন্দ করে (যার মধ্যে সিনট্যাক্টিক শক্তি এবং / অথবা কোন বস্তু ভিত্তিক দৃষ্টিভঙ্গি)। আরও ভাল রুবি প্রোগ্রামার আরও উপায় সন্ধান করতে থাকে।


এখন, আমি আরেকটি প্রশ্ন জিজ্ঞাসা করতে চাই, "রুবি পিছনের দিকে একটি রেঞ্জের মধ্য দিয়ে পুনরাবৃত্তি করার" ডান "উপায় কী?"! (এই প্রশ্নটি আমি কীভাবে এই পৃষ্ঠায় এসেছি))

এটি করা ভাল (সামনের দিকে):

(1..10).each{|i| puts "i=#{i}" }

তবে আমি (পিছনের দিকে) করতে পছন্দ করি না:

(1..10).to_a.reverse.each{|i| puts "i=#{i}" }

ঠিক আছে, আমি আসলে এটি খুব বেশি কিছু করতে আপত্তি করি না, তবে আমি যখন পিছনের দিকে যেতে শিখছি তখন আমি আমার ছাত্রদের একটি দুর্দান্ত প্রতিসাম্য প্রদর্শন করতে চাই (অর্থাত্ ন্যূনতম পার্থক্য সহ, যেমন কেবল একটি বিপরীত বা একটি ধাপ -1 যোগ করা, তবে ছাড়া) অন্য কিছু পরিবর্তন করে)। আপনি (প্রতিসাম্য জন্য) করতে পারেন:

(a=*1..10).each{|i| puts "i=#{i}" }

এবং

(a=*1..10).reverse.each{|i| puts "i=#{i}" }

যা আমি বেশি পছন্দ করি না, তবে আপনি করতে পারবেন না

(*1..10).each{|i| puts "i=#{i}" }
(*1..10).reverse.each{|i| puts "i=#{i}" }
#
(1..10).step(1){|i| puts "i=#{i}" }
(1..10).step(-1){|i| puts "i=#{i}" }
#
(1..10).each{|i| puts "i=#{i}" }
(10..1).each{|i| puts "i=#{i}" }   # I don't want this though.  It's dangerous

আপনি শেষ পর্যন্ত করতে পারে

class Range

  def each_reverse(&block)
    self.to_a.reverse.each(&block)
  end

end

তবে আমি অবজেক্ট ওরিয়েন্টেড পদ্ধতির পরিবর্তে খাঁটি রুবিকে শিখতে চাই (ঠিক এখনও)। আমি পিছনে পুনরাবৃত্তি করতে চাই:

  • একটি অ্যারে তৈরি না করে (0..1000000000 বিবেচনা করুন)
  • যে কোনও রেঞ্জের জন্য কাজ করা (উদাহরণস্বরূপ স্ট্রিংস, শুধুমাত্র পূর্ণসংখ্যার নয়)
  • কোনও অতিরিক্ত অবজেক্ট ভিত্তিক শক্তি ব্যবহার না করে (অর্থাত্ কোনও শ্রেণি পরিবর্তন নয়)

আমি বিশ্বাস করি কোনও predপদ্ধতি সংজ্ঞা না দিয়ে এটি অসম্ভব , যার অর্থ এটি ব্যাপ্তি শ্রেণিটি ব্যবহারের জন্য পরিবর্তন করা। আপনি যদি এটি করতে পারেন দয়া করে আমাকে জানান, অন্যথায় অসম্ভবতার নিশ্চিতকরণ প্রশংসিত হবে যদিও এটি হতাশ হবে। সম্ভবত রুবি 1.9 এটি সম্বোধন করে।

(এটি পড়ার জন্য আপনার সময়ের জন্য ধন্যবাদ।)


5
1.upto(10) do |i| puts i endএবং 10.downto(1) do puts i endধরনের আপনি চাইছিলেন প্রতিসাম্যতা দেয়। আশা করি এইটি কাজ করবে. এটি স্ট্রিং এবং এর জন্য কাজ করবে কিনা তা নিশ্চিত নয়।
সুরেন

(1..10)। To_a.sort {| x, y | y <=> x} .আচ {| i | "i = # {i}"} রাখে - বিপরীতে আরও ধীর হয়।
ডেভিডস্লভ

আপনি পারেন [*1..10].each{|i| puts "i=#{i}" }
হাউলেথ

19

যখন আপনার উভয়ের প্রয়োজন হয় তখন প্রতিটি_ইয়েথ_ইন্ডেক্স ব্যবহার করুন।

ary.each_with_index { |val, idx| # ...

12

অন্যান্য উত্তরগুলি ঠিক আছে, তবে আমি অন্য একটি পেরিফেরিয়াল জিনিসটি উল্লেখ করতে চেয়েছিলাম: অ্যারেগুলি আদেশ করা হয়েছে, যেখানে হ্যাশগুলি 1.8 তে নেই। (রুবি ১.৯-এ, হ্যাশগুলি কীগুলির সন্নিবেশ ক্রমের মাধ্যমে অর্ডার করা হয়েছে।) সুতরাং অ্যারেগুলির মতো একইভাবে / ক্রমানুসারে একটি হ্যাশটি পুনরাবৃত্তি করার আগে 1.9 এর আগে বুদ্ধিমান হবে না, যা সর্বদা একটি নির্দিষ্ট ক্রম ছিল। পিএইচপি এসোসিয়েটিভ অ্যারেগুলির জন্য ডিফল্ট অর্ডার কী তা আমি জানি না (সম্ভবত আমার গুগল ফু এটি নির্ধারণের পক্ষে যথেষ্ট শক্তিশালী নয়) তবে আপনি কীভাবে নিয়মিত পিএইচপি অ্যারে এবং পিএইচপি সহযোগী অ্যারে বিবেচনা করতে পারবেন তা আমি জানি না to এই প্রসঙ্গে "একই" হোন, যেহেতু সহযোগী অ্যারেগুলির ক্রমটি অপরিজ্ঞাত বলে মনে হচ্ছে।

এই হিসাবে, রুবি উপায়টি আমার কাছে আরও স্পষ্ট এবং স্বজ্ঞাত বলে মনে হচ্ছে। :)


1
হ্যাশ এবং অ্যারে একই জিনিস! অ্যারে মানচিত্রকে বস্তুতে পূর্ণসংখ্যার সাথে মানচিত্রের অবজেক্টগুলিকে হ্যাশ করে। অ্যারে হ্যাশগুলির কেবল বিশেষ মামলা, না?
টম লেহম্যান

1
আমি যেমন বলেছি, একটি অ্যারে হ'ল অর্ডার করা সেট। একটি ম্যাপিং (জেনেরিক অর্থে) আনঅর্ডারড। আপনি যদি কী সেটটি পূর্ণসংখ্যার (যেমন অ্যারে সহ) সীমাবদ্ধ করেন তবে কী সেটটি একটি অর্ডার থাকে তা ঠিক ঘটে। জেনেরিক ম্যাপিংয়ে (হ্যাশ / সহযোগী অ্যারে), কীগুলির কোনও অর্ডার নাও থাকতে পারে।
পিস্তোস

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

9

অ্যারে এবং হ্যাশগুলির সাথে ধারাবাহিকভাবে একই কাজ করার চেষ্টা করা কেবল কোডের গন্ধ হতে পারে তবে আমার ঝুঁকির সাথে কর্ডার্স অর্ধ-বানর-প্যাচার হিসাবে চিহ্নিত করা যদি আপনি সামঞ্জস্যপূর্ণ আচরণের সন্ধান করেন তবে এই কৌশলটি কি এই কৌশলটি করবে? :

class Hash
    def each_pairwise
        self.each { | x, y |
            yield [x, y]
        }
    end
end

class Array
    def each_pairwise
        self.each_with_index { | x, y |
            yield [y, x]
        }
    end
end

["a","b","c"].each_pairwise { |x,y|
    puts "#{x} => #{y}"
}

{"a" => "Aardvark","b" => "Bogle","c" => "Catastrophe"}.each_pairwise { |x,y|
    puts "#{x} => #{y}"
}

7

নিয়ন্ত্রণের স্বাধীনতার দ্বারা সাজানো আপনার প্রশ্নের তালিকাভুক্ত চারটি বিকল্প এখানে রয়েছে। আপনার প্রয়োজনের উপর নির্ভর করে আপনি একটি আলাদা ব্যবহার করতে চাইতে পারেন।

  1. কেবল মূল্যবোধের মধ্য দিয়ে যান:

    array.each
  2. সূচকগুলির মধ্যে কেবল যান:

    array.each_index
  3. সূচকগুলি + সূচক ভেরিয়েবলের মাধ্যমে যান:

    for i in array
  4. লুপ গণনা + সূচক পরিবর্তনশীল:

    array.length.times do | i |

5

আমি একটি হ্যাশ ব্যবহার করে একটি মেনু ( ক্যাম্পিং এবং মারকাবিতে ) তৈরি করার চেষ্টা করছিলাম ।

প্রতিটি আইটেমের 2 টি উপাদান রয়েছে: একটি মেনু লেবেল এবং একটি ইউআরএল , সুতরাং একটি হ্যাশটি সঠিক বলে মনে হয়েছিল, তবে 'হোম' এর জন্য '/' URL সর্বদা সর্বশেষে উপস্থিত হয়েছিল (যেমন আপনি একটি হ্যাশের প্রত্যাশা রেখেছিলেন), তাই মেনু আইটেমগুলি ভুল হিসাবে উপস্থিত হয়েছিল অর্ডার।

একটি অ্যারে ব্যবহার each_sliceকরে কাজটি করে:

['Home', '/', 'Page two', 'two', 'Test', 'test'].each_slice(2) do|label,link|
   li {a label, :href => link}
end

প্রতিটি মেনু আইটেমের জন্য অতিরিক্ত মান যুক্ত করা (যেমন একটি সিএসএস আইডি নামের মতো) কেবল স্লাইসের মান বাড়ানো। সুতরাং, একটি হ্যাশের মতো তবে কয়েকটি সংখ্যক আইটেম সমন্বিত গোষ্ঠীগুলির সাথে। পারফেক্ট।

সুতরাং এটি কেবল অজান্তেই কোনও সমাধানের ইঙ্গিত দেওয়ার জন্য ধন্যবাদ বলার জন্য!

সুস্পষ্ট, তবে উল্লেখ করার মতো: আমি স্লাইস মান দ্বারা অ্যারের দৈর্ঘ্য বিভাজ্য কিনা তা পরীক্ষা করার পরামর্শ দিই।


4

আপনি ব্যবহার করেন তাহলে গণনীয় mixin (যেমন পাগল করে) আপনি পিএইচপি snippet তালিকাভুক্ত অনুরূপ কিছু করতে পারেন। কেবল প্রতিটি_স্লাইস পদ্ধতিটি ব্যবহার করুন এবং হ্যাশটিকে সমতল করুন।

require 'enumerator' 

['a',1,'b',2].to_a.flatten.each_slice(2) {|x,y| puts "#{x} => #{y}" }

# is equivalent to...

{'a'=>1,'b'=>2}.to_a.flatten.each_slice(2) {|x,y| puts "#{x} => #{y}" }

কম বানর-প্যাচিং প্রয়োজন।

তবে আপনার যখন পুনরাবৃত্ত অ্যারে বা অ্যারে মান সহ একটি হ্যাশ থাকে তখন এটি সমস্যার সৃষ্টি করে। রুবি ১.৯-এ এই সমস্যাটি সমতল পদ্ধতিতে একটি পরামিতি দিয়ে সমাধান করা হয়েছে যা নির্দিষ্ট করে কত গভীর পুনরাবৃত্তি করতে হয়।

# Ruby 1.8
[1,2,[1,2,3]].flatten
=> [1,2,1,2,3]

# Ruby 1.9
[1,2,[1,2,3]].flatten(0)
=> [1,2,[1,2,3]]

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


2

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

আপনি যদি কিছু নির্দিষ্ট কাজ করার বিষয়ে স্বাচ্ছন্দ্য বোধ করেন তবে এটি কাজ করুন, যদি না এটি কাজ করে - তবে এখন আরও ভাল উপায় সন্ধানের সময় এসেছে।


2

রুবি ২.১ এ, প্রতিটি_পথ_ইন্ডেক্স পদ্ধতিটি সরানো হয়েছে। পরিবর্তে আপনি প্রতিটি_আইডেক্স ব্যবহার করতে পারেন

উদাহরণ:

a = [ "a", "b", "c" ]
a.each_index {|x| print x, " -- " }

সৃষ্টি করে:

0 -- 1 -- 2 --

4
এটি সত্য নয়। গৃহীত উত্তরের মন্তব্যে যেমন বলা হয়েছে, each_with_indexডকুমেন্টেশনে কারণটির উপস্থিতি নেই কারণ এটি Enumerableমডিউল দ্বারা সরবরাহ করা হয়েছিল ।
ihaztehcodez

0

উভয় অ্যারে এবং হ্যাশগুলির মাধ্যমে পুনরাবৃত্তি করার জন্য একই পদ্ধতিটি ব্যবহার করা অর্থপূর্ণ হয়ে উঠেছে, উদাহরণস্বরূপ নেস্টেড হ্যাশ-এবং-অ্যারে কাঠামোগুলি প্রায়শই পার্সারগুলির ফলে জেএসএন ফাইল পড়া থেকে শুরু করে প্রক্রিয়াজাত করা ..

একটি চতুর উপায় যা এখনও উল্লেখ করা হয়নি তা হ'ল এটি কীভাবে স্ট্যান্ডার্ড লাইব্রেরি এক্সটেনশনের রুবি ফেসস লাইব্রেরিতে করা হয়। থেকে এখানে :

class Array

  # Iterate over index and value. The intention of this
  # method is to provide polymorphism with Hash.
  #
  def each_pair #:yield:
    each_with_index {|e, i| yield(i,e) }
  end

end

ইতিমধ্যে আছে Hash#each_pair, একটি উপনাম Hash#each। সুতরাং এই প্যাচ পরে, আমরা Array#each_pairhashes এবং অ্যারে উভয়ের মাধ্যমে পুনরাবৃত্তি করতে একে অন্যকে পরিবর্তন এবং ব্যবহার করতে পারেন। এটি ওপি'র পর্যবেক্ষিত উন্মাদাকে স্থির করে যা Array#each_with_indexব্লক যুক্তিগুলির তুলনায় বিপরীত হয়েছে Hash#each। ব্যবহারের উদাহরণ:

my_array = ['Hello', 'World', '!']
my_array.each_pair { |key, value| pp "#{key}, #{value}" }

# result: 
"0, Hello"
"1, World"
"2, !"

my_hash = { '0' => 'Hello', '1' => 'World', '2' => '!' }
my_hash.each_pair { |key, value| pp "#{key}, #{value}" }

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