এমন কোনও কারণ আছে যে আমরা রুবিতে "বিপরীত রেঞ্জ" নিয়ে পুনরাবৃত্তি করতে পারি না?


104

আমি একটি রেঞ্জ ব্যবহার করে পিছনের দিকে পুনরাবৃত্তি করার চেষ্টা করেছি এবং each:

(4..0).each do |i|
  puts i
end
==> 4..0

আইট্রেটেশন মাধ্যমে 0..4সংখ্যা লিখেছেন। অন্য সীমাতে r = 4..0মনে হয় ঠিক আছে r.first == 4,, r.last == 0

এটি আমার কাছে আশ্চর্যজনক বলে মনে হয় যে উপরে নির্মাণগুলি প্রত্যাশিত ফলাফলটি দেয় না। এর কারণ কী? এই আচরণটি যুক্তিসঙ্গত হলে পরিস্থিতিগুলি কী কী?


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

1
পরিসীমা নিজেই কনভেনশন দ্বারা ফিরে আসে। যেহেতু .eachবিবৃতিটি কোনও কিছু সংশোধন করে নি, ফেরত দেওয়ার জন্য কোনও গণিত "ফলাফল" নেই। যখন এটি হয়, রুবি সাধারণত সাফল্য এবং nilত্রুটিতে আসল বস্তুটি ফেরত দেয় । এটি আপনাকে ifবিবৃতিতে শর্ত হিসাবে এ জাতীয় এক্সপ্রেশন ব্যবহার করতে দেয় ।
বিটিএ

উত্তর:


99

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

যদি আপনি এর মতো একটি পরিসীমা পেরিয়ে পিছনের দিকে যেতে চান তবে আপনি সর্বদা ব্যবহার করতে পারেন downto:

$ r = 10..6
=> 10..6

$ (r.first).downto(r.last).each { |i| puts i }
10
9
8
7
6

পুনরাবৃত্তির অনুমতি দেওয়া এবং নিয়মিতভাবে বিপরীত সীমাগুলির সাথে কেন ডিল করা দু'জনের পক্ষে কেন কঠোর তা সম্পর্কে অন্যদের থেকে এখানে আরও কিছু চিন্তাভাবনা রয়েছে।


10
আমি মনে করি 1 থেকে 100 বা 100 থেকে 1 অবধি বিস্তৃত হওয়ার অর্থ স্বজ্ঞাতভাবে 1 পদক্ষেপটি ব্যবহার করা উচিত। যদি কেউ আলাদা পদক্ষেপ চায়, ডিফল্টটি পরিবর্তন করে। একইভাবে, আমার জন্য (কমপক্ষে) 1 লা জানুয়ারি থেকে 16 ই আগস্ট পর্যন্ত পুনরাবৃত্তি করার অর্থ দিনগুলি পা রেখে যাওয়া। আমি মনে করি প্রায়শই এমন কিছু বিষয় রয়েছে যা আমরা সাধারণত একমত হতে পারি, কারণ আমরা স্বজ্ঞাতভাবে সেটিকে বোঝাই। আপনার উত্তরের জন্য ধন্যবাদ, আপনার দেওয়া লিঙ্কটিও কার্যকর ছিল।
ফিফিগিরি

3
আমি এখনও মনে করি যে অনেকগুলি পরিসরের জন্য "স্বজ্ঞাত" পুনরাবৃত্তি সংজ্ঞায়িত করা ধারাবাহিকভাবে করা চ্যালেঞ্জ, এবং আমি সম্মত নই যে তারিখগুলিতে পুনরাবৃত্তিটি স্বজ্ঞাতভাবে 1 দিনের সমান পদক্ষেপকে বোঝায় - সর্বোপরি, একটি দিন নিজেই ইতিমধ্যে একটি পরিসীমা সময় (মধ্যরাত থেকে মধ্যরাত) উদাহরণস্বরূপ, কে বলবেন যে "জানুয়ারি 1 থেকে 18 আগস্ট" (ঠিক 20 সপ্তাহ) দিনের পরিবর্তে সপ্তাহের পুনরাবৃত্তি বোঝায় না? কেন ঘন্টা বা মিনিট বা দ্বিতীয় দ্বারা পুনরাবৃত্তি হয় না?
জন Feminella

8
.eachঅপ্রয়োজনীয় আছে, 5.downto(1) { |n| puts n }কাজ করে জরিমানা। এছাড়াও, সমস্ত r.first r.last স্টাফের পরিবর্তে, কেবল করুন (6..10).reverse_each
এম কে 12

@ এম কে 12: 100% একমত, আমি কেবল নতুন রুবিবাদীদের পক্ষে অতি সুস্পষ্ট হওয়ার চেষ্টা করছিলাম। যদিও এটি খুব বিভ্রান্তিকর।
জন Feminella

কোনও ফর্মে বছর যোগ করার চেষ্টা করার সময়, আমি ব্যবহার করেছি:= f.select :model_year, (Time.zone.now.year + 1).downto(Time.zone.now.year - 100).to_a
এরিক নরক্রস

92

কেমন হয় (0..1).reverse_eachযা পরিসীমা পিছন iterates?


1
এটি অস্থায়ী অ্যারে তৈরি করে, কমপক্ষে ২.৪.১
রুবি -ডোক.আর.অর্গ.অর্ডার

1
এটি আমার জন্য বিভিন্ন তারিখের বাছাইয়ের জন্য (Date.today.beginning_of_year..Date.today.yesterday).reverse_eachধন্যবাদ ধন্যবাদ
ড্যানিয়েল

18

পরিধিটির প্রথম অবজেক্টে পদ্ধতিটিকে eachকল করে রুবিতে একটি ব্যাপ্তির মধ্যে আইট্রেটিং succ

$ 4.succ
=> 5

এবং 5 সীমার বাইরে।

আপনি এই হ্যাক দিয়ে বিপরীত পুনরাবৃত্তি সিমুলেট করতে পারেন:

(-4..0).each { |n| puts n.abs }

জন উল্লেখ করেছেন যে এটি 0 টি বিস্তৃত হলে এটি কাজ করবে না This

>> (-2..2).each { |n| puts -n }
2
1
0
-1
-2
=> -2..2

আমি বলতে চাই না যে আমি তাদের মধ্যে আসলেই পছন্দ করি কারণ তারা একপ্রকার উদ্দেশ্যটিকে অস্পষ্ট করে।


2
নাহয় আপনি পারবেন .abs ব্যবহার না করে -1 দিয়ে গুণ করে।
জোনাস এলফস্ট্রাম

12

"প্রোগ্রামিং রুবি" বই অনুসারে, রেঞ্জ অবজেক্টটি ব্যাপ্তির দুটি প্রান্তটি সংরক্ষণ .succকরে এবং মধ্যবর্তী মানগুলি তৈরি করতে সদস্যকে ব্যবহার করে । আপনি আপনার পরিসীমাতে কী ধরণের ডেটা ব্যবহার করছেন তার উপর নির্ভর করে আপনি সর্বদা একটি সাবক্লাস তৈরি করতে Integerএবং সদস্যটিকে পুনরায় সংজ্ঞায়িত করতে .succপারেন যাতে এটি একটি বিপরীত পুনরুদ্ধারের মতো কাজ করে (আপনি সম্ভবত এটিও পুনরায় সংজ্ঞায়িত করতে চান .next)।

রেঞ্জ ব্যবহার না করে আপনি যে ফলাফলগুলি সন্ধান করছেন তা অর্জন করতে পারেন। এটা চেষ্টা কর:

4.step(0, -1) do |i|
    puts i
end

এটি -1 এর পদক্ষেপে 4 থেকে 0 এ পদক্ষেপ নেবে। তবে, আমি জানি না এটি পূর্ণসংখ্যার যুক্তি ব্যতীত অন্য কোনও কিছুর জন্য কাজ করবে কিনা।



5

আপনি এমনকি একটি forলুপ ব্যবহার করতে পারেন :

for n in 4.downto(0) do
  print n
end

যা প্রিন্ট করে:

4
3
2
1
0

3

তালিকা যদি বড় না হয়। আমি মনে করি [*0..4].reverse.each { |i| puts i } সহজ উপায়।


2
আইএমও এটি বড় বলে ধরে নেওয়া ভাল। আমি সাধারণভাবে অনুসরণ করা সঠিক বিশ্বাস এবং অভ্যাস বলে মনে করি। এবং শয়তান কখনই ঘুমায় না, আমি নিজেকে বিশ্বাস করি না যে আমি মনে করি যেখানে আমি একটি অ্যারে দিয়ে পুনরাবৃত্তি করেছি। তবে আপনি ঠিক বলেছেন, যদি আমাদের 0 এবং 4 ধ্রুব থাকে, অ্যারে দিয়ে পুনরাবৃত্তি করা কোনও সমস্যা নাও করতে পারে।
ফিফিগিরি

1

যেমন বিটিএ বলেছে, কারণটি হ'ল তার শুরুতে Range#eachপ্রেরণ succকরে, তারপরে সেই succকলটির ফলাফলের দিকে , এবং ফলাফল শেষের মানের চেয়ে বেশি না হওয়া পর্যন্ত। আপনি কল করে 4 থেকে 0 পেতে পারবেন না succএবং বাস্তবে আপনি ইতিমধ্যে শেষের চেয়ে বড় শুরু করেছেন।


1

বিপরীত ব্যাপ্তির মাধ্যমে পুনরাবৃত্তিটি কীভাবে উপলব্ধি করা যায় সে সম্পর্কে আমি আরও একটি সম্ভাবনা যুক্ত করি। আমি এটি ব্যবহার করি না, তবে এটি একটি সম্ভাবনা। বানর প্যাচ রুবি কোর অবজেক্টগুলির জন্য এটি কিছুটা ঝুঁকিপূর্ণ।

class Range

  def each(&block)
    direction = (first<=last ? 1 : -1)
    i = first
    not_reached_the_end = if first<=last
                            lambda {|i| i<=last}
                          else
                            lambda {|i| i>=last}
                          end
    while not_reached_the_end.call(i)
      yield i
      i += direction
    end
  end
end

0

এটি আমার অলস ব্যবহারের ক্ষেত্রে কাজ করেছে

(-999999..0).lazy.map{|x| -x}.first(3)
#=> [999999, 999998, 999997]

0

ওপি লিখেছেন

এটি আমার কাছে আশ্চর্যজনক বলে মনে হয় যে উপরে নির্মাণগুলি প্রত্যাশিত ফলাফলটি দেয় না। এর কারণ কী? এই আচরণটি যুক্তিসঙ্গত হলে পরিস্থিতিগুলি কী কী?

না 'এটা করা যায়?' তবে যে প্রশ্নটি আসলে জিজ্ঞাসা করা হয়েছিল, তার আগে যা জিজ্ঞাসা করা হয়নি তার উত্তর দিতে:

$ irb
2.1.5 :001 > (0..4)
 => 0..4
2.1.5 :002 > (0..4).each { |i| puts i }
0
1
2
3
4
 => 0..4
2.1.5 :003 > (4..0).each { |i| puts i }
 => 4..0
2.1.5 :007 > (0..4).reverse_each { |i| puts i }
4
3
2
1
0
 => 0..4
2.1.5 :009 > 4.downto(0).each { |i| puts i }
4
3
2
1
0
 => 4

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

আসলে জিজ্ঞাসা করা প্রশ্নের উত্তর দিতে ...

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

nil.to_s
   .to_s
   .inspect

"" এর ফলাফল কিন্তু

nil.to_s
#  .to_s   # Don't want this one for now
   .inspect

ফলাফল স্বরূপ

 syntax error, unexpected '.', expecting end-of-input
 .inspect
 ^

আপনি সম্ভবত প্রত্যাশা করবেন << এবং অ্যারেগুলিতে সংযোজন করার জন্য একই হতে হবে, তবে

a = []
a << *[:A, :B]    # is illegal but
a.push *[:A, :B]  # isn't.

আপনি সম্ভবত 'গ্রেপ' এর ইউনিক্স কমান্ড-লাইনের সমতুল্য আচরণ করার প্রত্যাশা করতে পারেন তবে এটির নাম থাকা সত্ত্বেও এটি === মিলছে না = ~।

$ echo foo | grep .
foo
$ ruby -le 'p ["foo"].grep(".")'
[]

বিভিন্ন পদ্ধতি অপ্রত্যাশিতভাবে একে অপরের অপর নাম, তাই আপনাকে একই জিনিসটির একাধিক নাম শিখতে হবে - যেমন findএবং detect- এমনকি আপনি বেশিরভাগ বিকাশকারীকে পছন্দ করেন এবং কেবল কখনও কখনও এক বা অন্যটি ব্যবহার করেন। একই ঘটনা ঘটে যায় জন্য size, countএবংlength , ক্লাস যা প্রতিটি ভিন্নভাবে সংজ্ঞায়িত, অথবা এক বা দুই আদৌ সংজ্ঞায়িত করেন না ছাড়া।

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

এনভায়রনমেন্ট ভেরিয়েবল অবজেক্ট, ENV 'মার্জ' সমর্থন করে না, তাই আপনাকে লিখতে হবে

 ENV.to_h.merge('a': '1')

বোনাস হিসাবে, আপনি নিজের বা অন্য কারও কি ধরণের স্থিতিশীল তা নতুন করে সংজ্ঞায়িত করতে পারেন যদি সেগুলির কী হওয়া উচিত about


এটি কোনওভাবেই, আকার বা আকারে প্রশ্নের উত্তর দেয় না। এটি রুবি সম্পর্কে লেখক যে জিনিস পছন্দ করেন না সে সম্পর্কে উদাসীনতা ছাড়া কিছুই নয়।
Jörg W Mittag

জিজ্ঞাসা করা হয়নি এমন প্রশ্নের উত্তর দেওয়ার জন্য আপডেট করা হয়েছে, এটি ছাড়াও যা আসলে জিজ্ঞাসিত হয়েছিল। রেন্ট: ক্রিয়াপদ 1. ক্রোধে, মমত্বপূর্ণ উপায়ে দৈর্ঘ্যে কথা বলুন বা চিৎকার করুন। মূল উত্তরটি রাগান্বিত বা অনুভূতিযুক্ত ছিল না: এটি উদাহরণগুলির সাথে বিবেচিত প্রতিক্রিয়া ছিল।
android.weasel

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

আবার, আমি দেখতে ব্যর্থ হই grepযে কোনওভাবেই কোনও আকার, আকৃতি বা ফর্মের আচরণ যে খালি পরিসরে পুনরাবৃত্তি হওয়া কোনও বিকল্প নয় to এবং আমি কী দেখতে পাচ্ছি না যে খালি পরিসরে পুনরাবৃত্তি হ'ল কোনও বিকল্প নেই যে কোনওভাবেই আকার বা রূপ "অন্তহীন অবাক করা" এবং "ডান দিকের ভাঙ্গা" form
জার্গ ডব্লু মিট্টাগ

কারণ একটি পরিসীমা ৪.০ এর [4, 3, 2, 1, 0] এর সুস্পষ্ট উদ্দেশ্য রয়েছে তবে আশ্চর্যরূপে কোনও সতর্কতাও উত্থাপন করে না। এটি ওপিকে অবাক করেছে এবং এটি আমাকে অবাক করেছে, এবং সন্দেহজনকভাবে অন্যান্য অনেক লোককে অবাক করেছে। আমি অবাক করা আচরণের অন্যান্য উদাহরণগুলি তালিকাভুক্ত করেছি। আমি চাইলে আরও উদ্ধৃত করতে পারি। কিছু যখন আশ্চর্যজনক আচরণের নির্দিষ্ট পরিমাণের চেয়ে বেশি প্রদর্শিত হয়, তখন এটি 'ভাঙ্গা' অঞ্চলে প্রবাহিত হতে শুরু করে। ওভাররাইট করার সময় স্থিরকারীরা কীভাবে সতর্কতা উত্থাপন করে তার মতো কিছুটা, বিশেষত যখন পদ্ধতিগুলি না করে।
android.weasel

0

আমার পক্ষে সহজ উপায়টি হ'ল:

[*0..9].reverse

গণনার জন্য পুনরাবৃত্তি করার আরেকটি উপায়:

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