ইনজেকশন পদ্ধতির একটি সহজ ব্যাখ্যা প্রয়োজন


142
[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

আমি এই কোডটি দেখছি কিন্তু আমার মস্তিষ্ক কীভাবে 10 নম্বর ফলাফল হতে পারে তা নিবন্ধভুক্ত করছে না। এখানে কি ঘটছে তা বোঝানোর জন্য কেউ মনে করবে?

ruby  syntax 

3
উইকিপিডিয়া দেখুন : ভাঁজ (উচ্চতর অর্ডার ফাংশন) : ইনজেকশনটি "ভাঁজ বাম", যদিও (দুর্ভাগ্যক্রমে) প্রায়শই রুবি ব্যবহারে পার্শ্ব প্রতিক্রিয়া রয়েছে।
ব্যবহারকারী 2864740

উত্তর:


208

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

প্রক্রিয়া শেষে, ইনজেক্টটি জমা করে দেয়, যা এই ক্ষেত্রে অ্যারে বা 10 এর সমস্ত মানের যোগফল।

স্ট্রিং প্রতিনিধিত্ব করে কীডযুক্ত বস্তুর অ্যারে থেকে একটি হ্যাশ তৈরি করার জন্য এখানে আরও একটি সহজ উদাহরণ রয়েছে:

[1,"a",Object.new,:hi].inject({}) do |hash, item|
  hash[item.to_s] = item
  hash
end

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


দুর্দান্ত ব্যাখ্যা, তবে, ওপি দ্বারা প্রদত্ত উদাহরণে, কী ফিরিয়ে দেওয়া হচ্ছে (যেমন হ্যাশ আপনার উদাহরণে রয়েছে)। এটি ফলাফল + ব্যাখ্যার সাথে শেষ হয় এবং হ্যাঁ, একটি ফেরতের মান হওয়া উচিত?
প্রজোল

1
@ প্রজল দ্য result + explanationহ'ল সংস্থানকারী এবং ফেরতের মান উভয়কে রূপান্তর। এটি একটি অন্তর্নিহিত রিটার্ন করে এটি ব্লকের শেষ লাইন।
কেএ 01

87

inject( 0আপনার উদাহরণে) এবং একটি ব্লক দিয়ে শুরু করার জন্য একটি মান নেয় এবং এটি তালিকার প্রতিটি উপাদানগুলির জন্য একবারে সেই ব্লকটি চালায়।

  1. প্রথম পুনরাবৃত্তিতে এটি সূচনা মান এবং তালিকার প্রথম উপাদান হিসাবে প্রদত্ত মানকে পাস করে এবং এটি আপনার ব্লকটি ফিরে আসার মানকে (এই ক্ষেত্রে result + element) সংরক্ষণ করে।
  2. এরপরে এটি পুনরায় ব্লকটি চালায়, প্রথম যুক্তির হিসাবে প্রথম পুনরাবৃত্তি থেকে ফলাফলটি পাস করে এবং দ্বিতীয় যুক্তি হিসাবে তালিকা থেকে দ্বিতীয় উপাদানটি আবার ফলাফল সংরক্ষণ করে।
  3. তালিকার সমস্ত উপাদান গ্রাস না করা অবধি এটি এভাবেই চালিয়ে যায়।

এটি ব্যাখ্যা করার সবচেয়ে সহজ উপায় হ'ল প্রতিটি উদাহরণ কীভাবে কাজ করে তা উদাহরণস্বরূপ; এই ফলাফলটি কীভাবে মূল্যায়ন করা যেতে পারে তা দেখানোর একটি কল্পিত সেট:

[1, 2, 3, 4].inject(0) { |result, element| result + element }
[2, 3, 4].inject(0 + 1) { |result, element| result + element }
[3, 4].inject((0 + 1) + 2) { |result, element| result + element }
[4].inject(((0 + 1) + 2) + 3) { |result, element| result + element }
[].inject((((0 + 1) + 2) + 3) + 4) { |result, element| result + element }
(((0 + 1) + 2) + 3) + 4
10

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

2
নীচের চিত্রটি কীভাবে এটি প্রয়োগ করা যেতে পারে তার উপর ভিত্তি করে ; এটি অগত্যা ঠিক এইভাবে প্রয়োগ করা হয়নি। সে কারণেই আমি বলেছিলাম এটি একটি কল্পিত ধাপ steps এটি মৌলিক কাঠামো প্রদর্শন করে তবে সঠিক বাস্তবায়ন নয়।
ব্রায়ান ক্যাম্পবেল

27

ইনজেক্ট পদ্ধতির বাক্য গঠনটি নিম্নরূপ:

inject (value_initial) { |result_memo, object| block }

আসুন উপরের উদাহরণটি সমাধান করুন

[1, 2, 3, 4].inject(0) { |result, element| result + element }

যা আউটপুট হিসাবে 10 দেয় ।

সুতরাং, শুরু করার আগে আসুন দেখুন প্রতিটি ভেরিয়েবলের মধ্যে কী কী মান রয়েছে:

ফলাফল = 0 শূন্যটি ইনজেকশন থেকে এসেছে (মান) যা 0 is

উপাদান = 1 এটি অ্যারের প্রথম উপাদান।

ঠিক আছে !!! সুতরাং, আসুন উপরের উদাহরণটি বুঝতে শুরু করা যাক

ধাপ 1 [1, 2, 3, 4].inject(0) { |0, 1| 0 + 1 }

ধাপ ২ [1, 2, 3, 4].inject(0) { |1, 2| 1 + 2 }

ধাপ 3 [1, 2, 3, 4].inject(0) { |3, 3| 3 + 3 }

পদক্ষেপ: 4 [1, 2, 3, 4].inject(0) { |6, 4| 6 + 4 }

পদক্ষেপ: 5 [1, 2, 3, 4].inject(0) { |10, Now no elements left in the array, so it'll return 10 from this step| }

এখানে বোল্ড-ইটালিক মান হ'ল অ্যারে থেকে সরানো এবং সহজভাবে বোল্ড elements মানগুলি ফলস্বরূপ মান।

আমি আশা করি আপনি #injectপদ্ধতিটির কাজটি বুঝতে পেরেছেন #ruby


19

কোডটি অ্যারের মধ্যে চারটি উপাদানের উপরে পুনরাবৃত্তি করে এবং পূর্ববর্তী ফলাফলটিকে বর্তমান উপাদানটিতে যুক্ত করে:

  • 1 + 2 = 3
  • 3 + 3 = 6
  • 6 + 4 = 10

15

তারা কী বলেছিল, তবে এগুলিও নোট করুন যে আপনার সর্বদা "শুরুর মান" সরবরাহ করার দরকার নেই:

[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

হিসাবে একই

[1, 2, 3, 4].inject { |result, element| result + element } # => 10

চেষ্টা করে দেখুন, আমি অপেক্ষা করব।

যখন কোনও যুক্তি ইনজেকশনে পাস করা হয় না, প্রথম দুটি উপাদান প্রথম পুনরাবৃত্তিতে পাস হয়। উপরের উদাহরণে, ফলাফলটি 1 এবং উপাদানটি প্রথমবারের মতো 2 হয়, তাই ব্লকে আরও কম কল করা হয়।


14

আপনার ইনজেকশনের () এর ভিতরে থাকা নম্বরটি একটি শুরুর স্থান উপস্থাপন করে, এটি 0 বা 1000 হতে পারে the পাইপগুলির ভিতরে আপনার দুটি স্থানধারক রয়েছে | x, y | x =। ইনজেক্ট ('x') এর ভিতরে আপনার যে সংখ্যাটি ছিল এবং সেকেন্ডটি আপনার বস্তুর প্রতিটি পুনরাবৃত্তির প্রতিনিধিত্ব করে।

[1, 2, 3, 4].inject(5) { |result, element| result + element } # => 15

1 + 5 = 6 2 + 6 = 8 3 + 8 = 11 11 + 4 = 15


6

ইনজেকশন ব্লক প্রয়োগ করে

result + element

অ্যারে প্রতিটি আইটেম। পরবর্তী আইটেমের জন্য ("উপাদান"), ব্লক থেকে প্রাপ্ত মানটি "ফলাফল"। আপনি যেভাবে এটি (প্যারামিটার সহ) বলেছেন, সেই ফলাফলটির সাথে "ফলাফল" শুরু হয় result সুতরাং প্রভাব উপাদান যোগ করা হয়।


6

tldr; একটি গুরুত্বপূর্ণ উপায়ে injectপৃথক map: injectব্লকের শেষ সম্পাদনের মান প্রদান করে যেখানে mapএটির পুনরাবৃত্তি হওয়া অ্যারেরটি দেয়।

এর চেয়েও বেশি প্রতিটি ব্লক এক্সিকিউশনের মান প্রথম প্যারামিটারের মাধ্যমে পরবর্তী এক্সিকিউশনে ( resultএই ক্ষেত্রে) পাস হয়ে যায় এবং আপনি সেই মানটি আরম্ভ করতে পারেন ((0) অংশটি) ।

আপনার উপরের উদাহরণটি mapএভাবে ব্যবহার করে লেখা যেতে পারে :

result = 0 # initialize result
[1, 2, 3, 4].map { |element| result += element }
# result => 10

একই প্রভাব কিন্তু injectএখানে আরও সংক্ষিপ্ত।

আপনি প্রায়শই একটি অ্যাসাইনমেন্টটি mapব্লকে ঘটে দেখবেন , অন্যদিকে ব্লকটিতে একটি মূল্যায়ন ঘটে inject

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

result = [1, 2, 3, 4].inject(0) { |x, element| x + element }

আপনি সবার মতো হতে পারেন, "আমাকে দেখুন, আমি এগুলি কেবল একটি লাইনে সংযুক্ত করেছি," তবে আপনি xএকটি স্ক্র্যাচ ভেরিয়েবল হিসাবে অস্থায়ীভাবে মেমরিও বরাদ্দ দিয়েছিলেন যেহেতু আপনাকে ইতিমধ্যে resultকাজ করতে হবে বলে প্রয়োজনীয় ছিল না ।


4
[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

নিম্নলিখিতগুলির সমতুল্য:

def my_function(r, e)
  r+e
end

a = [1, 2, 3, 4]
result = 0

a.each do |value|
  result = my_function(result, value)
end

3

[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

সরল ইংরেজিতে, আপনি এই অ্যারে ( [1,2,3,4]) এর মাধ্যমে (পুনরাবৃত্তি) যাচ্ছেন । আপনি এই অ্যারেটি দিয়ে 4 বার পুনরাবৃত্তি করতে পারবেন, কারণ এখানে 4 টি উপাদান রয়েছে (1, 2, 3 এবং 4)। ইনজেকশন পদ্ধতিতে 1 টি যুক্তি (সংখ্যা 0) রয়েছে এবং আপনি সেই যুক্তিটি 1 ম এলিমেন্টে যুক্ত করবেন (0 + 1. এটি সমান 1)। 1 "ফলাফল" এ সংরক্ষিত হয়েছে। তারপরে আপনি সেই ফলাফলটি (যা 1) পরবর্তী উপাদানগুলিতে যুক্ত করুন (1 + 2. এটি 3)। এটি এখন ফলাফল হিসাবে সংরক্ষণ করা হবে। চালিয়ে যান: 3 + 3 সমান 6. এবং অবশেষে, 6 + 4 সমান 10 হয়।


2

এই কোডটি প্রারম্ভিক মানটি পাস না করার সম্ভাবনাটিকে অনুমতি দেয় না, তবে যা চলছে তা ব্যাখ্যা করতে সহায়তা করতে পারে।

def incomplete_inject(enumerable, result)
  enumerable.each do |item|
    result = yield(result, item)
  end
  result
end

incomplete_inject([1,2,3,4], 0) {|result, item| result + item} # => 10

1

এখান থেকে শুরু করুন এবং তারপরে যে সমস্ত পদ্ধতিগুলি ব্লকগুলি নিয়ে থাকে তা পর্যালোচনা করুন। http://ruby-doc.org/core-2.3.3/Enumerable.html#method-i-inject

এটি কি সেই ব্লক যা আপনাকে বিভ্রান্ত করে বা কেন আপনার পদ্ধতিতে একটি মূল্য রয়েছে? ভাল প্রশ্ন যদিও। সেখানে অপারেটর পদ্ধতি কী?

result.+

এটি কি হিসাবে শুরু হয়?

#inject(0)

আমরা কি এটা করতে পারি?

[1, 2, 3, 4].inject(0) { |result, element| result.+ element }

এটা কি কাজ করে?

[1, 2, 3, 4].inject() { |result = 0, element| result.+ element }

আপনি দেখতে পাচ্ছেন আমি এই ধারণাটি তৈরি করছি যে এটি অ্যারের সমস্ত উপাদানগুলিকে কেবল পরিমাণে যোগ করে এবং ডক্সে আপনি যে মেমো দেখেন তাতে একটি সংখ্যা দেয় yield

আপনি সর্বদা এটি করতে পারেন

 [1, 2, 3, 4].each { |element| p element }

অ্যারের সংখ্যাটি পুনরাবৃত্তি হতে দেখতে। এটিই মূল ধারণা।

এটি কেবলমাত্র ইনজেকশন বা হ্রাস হ'ল আপনাকে একটি মেমো বা কোনও প্রেরক পাঠানো হয় accum

আমরা একটি ফলাফল পেতে চেষ্টা করতে পারে

[1, 2, 3, 4].each { |result = 0, element| result + element }

কিন্তু কিছুই ফিরে আসে না তাই এটি ঠিক আগের মতোই কাজ করে

[1, 2, 3, 4].each { |result = 0, element| p result + element }

উপাদান পরিদর্শক ব্লক।


1

এটি ব্যাখ্যাটি বোঝার জন্য একটি সহজ এবং মোটামুটি সহজ:

"প্রাথমিক মান" সম্পর্কে ভুলে যান কারণ এটি শুরুতে কিছুটা বিভ্রান্তিকর।

> [1,2,3,4].inject{|a,b| a+b}
=> 10

আপনি উপরের বিষয়গুলি বুঝতে পারবেন: আমি 1,2,3,4 এর মধ্যে একটি "অ্যাডিং মেশিন" ইনজেকশন দিচ্ছি। অর্থ, এটি 1 ♫ 2 ♫ 3 ♫ 4 এবং ♫ একটি অ্যাডিং মেশিন, তাই এটি 1 + 2 + 3 + 4 এর সমান এবং এটি 10 ​​হয়।

আপনি আসলে +তাদের মধ্যে একটি ইনজেক্ট করতে পারেন :

> [1,2,3,4].inject(:+)
=> 10

এবং এটি এর মতো, +1,2,3,4 এর মধ্যে একটি ইনজেক্ট করুন , এটি 1 + 2 + 3 + 4 তৈরি করে এবং এটি 10। :+এটি রুবিকে +প্রতীক আকারে নির্দিষ্ট করার পদ্ধতি।

এটি বোঝা বেশ সহজ এবং স্বজ্ঞাত। এবং যদি আপনি পর্যায়ক্রমে এটি কীভাবে কাজ করে তা বিশ্লেষণ করতে চান তবে এটির মতো: 1 এবং 2 গ্রহণ করে এখন সেগুলি যুক্ত করুন এবং ফলস্বরূপ, প্রথমে এটি সংরক্ষণ করুন (যা 3) এবং এখন, পরবর্তীটি সঞ্চিত রয়েছে মান 3 এবং অ্যারের উপাদান 3 একটি + বি প্রসেসের মধ্য দিয়ে যাচ্ছে, যা 6, এবং এখন এই মানটি সংরক্ষণ করে এখন 6 এবং 4 এ + বি প্রক্রিয়াটির মধ্য দিয়ে যায় এবং 10 হয় আপনি মূলত করছেন

((1 + 2) + 3) + 4

এবং 10 "" প্রাথমিক মান "দিয়ে শুরু 0হওয়া কেবল একটি" বেস "। অনেক ক্ষেত্রে, আপনার এটির দরকার নেই। আপনার যদি 1 * 2 * 3 * 4 প্রয়োজন হয় এবং এটি হয় তা কল্পনা করুন

[1,2,3,4].inject(:*)
=> 24

এবং এটি সম্পন্ন হয়েছে। 1পুরো জিনিসটি দিয়ে গুণতে আপনার কোনও "প্রাথমিক মান" লাগবে না 1


0

.আইনজেক্ট () পদ্ধতির অন্য একটি রূপ রয়েছে যা খুব সহায়ক [4,5]। ইনজেক্ট (&: +) যা এই অঞ্চলের সমস্ত উপাদানকে যুক্ত করবে


0

এটি অন্যথায় reduceবা foldআপনি যদি অন্য ভাষার সাথে পরিচিত হন।


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