কিভাবে অ্যারে থেকে গড় পাবেন?
আমার যদি অ্যারে থাকে:
[0,4,8,2,5,0,2,6]
গড় আমাকে 3.375 দেবে।
কিভাবে অ্যারে থেকে গড় পাবেন?
আমার যদি অ্যারে থাকে:
[0,4,8,2,5,0,2,6]
গড় আমাকে 3.375 দেবে।
উত্তর:
এটা চেষ্টা কর:
arr = [5, 6, 7, 8]
arr.inject{ |sum, el| sum + el }.to_f / arr.size
=> 6.5
লক্ষ করুন .to_f
, যা আপনি পূর্ণসংখ্যা বিভাগ থেকে কোনও সমস্যা এড়াতে চাইবেন। আপনি এটি করতে পারেন:
arr = [5, 6, 7, 8]
arr.inject(0.0) { |sum, el| sum + el } / arr.size
=> 6.5
Array
অন্য একজন মন্তব্যকারী যেমন পরামর্শ দিয়েছে তার অংশ হিসাবে আপনি এটিকে সংজ্ঞায়িত করতে পারেন , তবে আপনাকে পূর্ণসংখ্যা বিভাগ এড়ানো দরকার বা আপনার ফলাফলগুলি ভুল হবে। এছাড়াও, এটি প্রতিটি সম্ভাব্য উপাদান ধরণের ক্ষেত্রে সাধারণত প্রযোজ্য নয় (স্পষ্টতই, গড় গড় হতে পারে এমন জিনিসগুলির জন্য গড় গড়ে তোলে কেবল)। তবে আপনি যদি সেই পথে যেতে চান তবে এটি ব্যবহার করুন:
class Array
def sum
inject(0.0) { |result, el| result + el }
end
def mean
sum / size
end
end
আপনি যদি inject
আগে না দেখে থাকেন তবে এটি প্রদর্শিত হওয়ার মতো যাদুকর নয়। এটি প্রতিটি উপাদানের উপর পুনরাবৃত্তি করে এবং তারপরে এটিতে একটি সঞ্চয়ের মান প্রয়োগ করে। এর পরে সংযোজকটি পরবর্তী উপাদানটির হাতে দেওয়া হয়। এই ক্ষেত্রে, আমাদের সংগ্রহকারী কেবল একটি পূর্ণসংখ্যা যা পূর্ববর্তী সমস্ত উপাদানগুলির যোগফলকে প্রতিফলিত করে।
সম্পাদনা করুন: মন্তব্যকারী ডেভ রায় একটি দুর্দান্ত উন্নতির প্রস্তাব করেছেন।
সম্পাদনা করুন: মন্তব্যকারী গ্লেন জ্যাকম্যানের প্রস্তাবনাটি ব্যবহার করে arr.inject(:+).to_f
খুব সুন্দর তবে সম্ভবত কী চলছে তা আপনি যদি জানেন না তবে কিছুটা চালাকও। :+
প্রতীক; যখন ইনজেকশনে পাস করা হয় তখন এটি সংযোজকের মানটির বিপরীতে প্রতিটি উপাদানকে প্রতীক দ্বারা চিহ্নিত পদ্ধতি প্রয়োগ করে (এই ক্ষেত্রে সংযোজন অপারেশন)।
arr.inject(0.0) { |sum,el| sum + el } / arr.size
।
inject
ডকুমেন্টেশনে উল্লিখিত ইন্টারফেসের অংশ । to_proc
অপারেটর &
।
Array#inject
রেলগুলি ব্যবহার করেন তবে এখানে ওভারকিল। শুধু ব্যবহার #sum
। উদাহরণস্বরূপarr.sum.to_f / arr.size
a = [0,4,8,2,5,0,2,6]
a.instance_eval { reduce(:+) / size.to_f } #=> 3.375
এটি ব্যবহার করে না এমন একটি সংস্করণ হ'ল instance_eval
:
a = [0,4,8,2,5,0,2,6]
a.reduce(:+) / a.size.to_f #=> 3.375
instance_eval
কেবল a
একবার নির্দিষ্ট করে দেওয়ার সময় আপনাকে কোডটি চালাতে দেয় , যাতে এটি অন্যান্য কমান্ডের সাহায্যে শৃঙ্খলিত হতে পারে। এর random_average = Array.new(10) { rand(10) }.instance_eval { reduce(:+) / size.to_f }
পরিবর্তেrandom = Array.new(10) { rand(10) }; random_average = random.reduce(:+) / random.size
self
সেই ব্লকের ভিতরে ভেরিয়েবল বা কোনও পদ্ধতি অ্যাক্সেস করার চেষ্টা করেন এবং সমস্যাটি সমাধান করতে চান তবে) রূপান্তর instance_eval
বা ডিএসএল এর জন্য আরও বেশি।
আমি বিশ্বাস করি এর সহজ উত্তরটি
list.reduce(:+).to_f / list.size
reduce
এটি Enumerable
ব্যবহৃত মিক্সিনের একটি পদ্ধতি Array
। এবং এর নাম সত্ত্বেও, আমি @ শুভু ... এর সাথে একমত হয়েছি যদি না আপনি যদি প্রয়োগগুলি ব্যবহার করে রেলগুলি ব্যবহার করেন sum
।
আমি ম্যাথ.এভারেজ (মান) এর জন্য প্রত্যাশী ছিলাম, তবে এরকম কোনও ভাগ্য নেই।
values = [0,4,8,2,5,0,2,6]
average = values.sum / values.size.to_f
sum
তাই এই 6 বছর পর একটি সঠিক উত্তর, জ্যোতিষী পুরস্কার যোগ্য উপস্থিত হতে পারে, পদ্ধতি।
রুবি সংস্করণ> = 2.4 এর একটি পরিসংখ্যক # যোগ পদ্ধতি রয়েছে।
এবং ভাসমান পয়েন্ট গড় পেতে, আপনি পূর্ণসংখ্যা # এফডিআইভি ব্যবহার করতে পারেন
arr = [0,4,8,2,5,0,2,6]
arr.sum.fdiv(arr.size)
# => 3.375
পুরানো সংস্করণগুলির জন্য:
arr.reduce(:+).fdiv(arr.size)
# => 3.375
শীর্ষ সমাধানগুলির কয়েকটি মানদণ্ড (সবচেয়ে দক্ষতার সাথে):
array = (1..10_000_000).to_a
Benchmark.bm do |bm|
bm.report { array.instance_eval { reduce(:+) / size.to_f } }
bm.report { array.sum.fdiv(array.size) }
bm.report { array.sum / array.size.to_f }
bm.report { array.reduce(:+).to_f / array.size }
bm.report { array.reduce(:+).try(:to_f).try(:/, array.size) }
bm.report { array.inject(0.0) { |sum, el| sum + el }.to_f / array.size }
bm.report { array.reduce([ 0.0, 0 ]) { |(s, c), e| [ s + e, c + 1 ] }.reduce(:/) }
end
user system total real
0.480000 0.000000 0.480000 (0.473920)
0.500000 0.000000 0.500000 (0.502158)
0.500000 0.000000 0.500000 (0.508075)
0.510000 0.000000 0.510000 (0.512600)
0.520000 0.000000 0.520000 (0.516096)
0.760000 0.000000 0.760000 (0.767743)
1.530000 0.000000 1.530000 (1.534404)
array = Array.new(10) { rand(0.5..2.0) }
Benchmark.bm do |bm|
bm.report { 1_000_000.times { array.reduce(:+).to_f / array.size } }
bm.report { 1_000_000.times { array.sum / array.size.to_f } }
bm.report { 1_000_000.times { array.sum.fdiv(array.size) } }
bm.report { 1_000_000.times { array.inject(0.0) { |sum, el| sum + el }.to_f / array.size } }
bm.report { 1_000_000.times { array.instance_eval { reduce(:+) / size.to_f } } }
bm.report { 1_000_000.times { array.reduce(:+).try(:to_f).try(:/, array.size) } }
bm.report { 1_000_000.times { array.reduce([ 0.0, 0 ]) { |(s, c), e| [ s + e, c + 1 ] }.reduce(:/) } }
end
user system total real
0.760000 0.000000 0.760000 (0.760353)
0.870000 0.000000 0.870000 (0.876087)
0.900000 0.000000 0.900000 (0.901102)
0.920000 0.000000 0.920000 (0.920888)
0.950000 0.000000 0.950000 (0.952842)
1.690000 0.000000 1.690000 (1.694117)
1.840000 0.010000 1.850000 (1.845623)
class Array
def sum
inject( nil ) { |sum,x| sum ? sum+x : x }
end
def mean
sum.to_f / size.to_f
end
end
[0,4,8,2,5,0,2,6].mean
nil
0 এর চেয়ে যোগফল কেন হওয়া উচিত ?
আমাকে এমন কিছু প্রতিযোগিতায় নিয়ে আসি যা বিভাগকে শূন্য সমস্যার সমাধান করে:
a = [1,2,3,4,5,6,7,8]
a.reduce(:+).try(:to_f).try(:/,a.size) #==> 4.5
a = []
a.reduce(:+).try(:to_f).try(:/,a.size) #==> nil
আমাকে অবশ্যই স্বীকার করতে হবে যে "চেষ্টা" একটি রেলস সহায়ক। তবে আপনি সহজেই এটি সমাধান করতে পারেন:
class Object;def try(*options);self&&send(*options);end;end
class Array;def avg;reduce(:+).try(:to_f).try(:/,size);end;end
বিটিডাব্লু: আমি মনে করি এটি সঠিক যে খালি তালিকার গড় শূন্য। কোনও কিছুর গড়পড়তা কিছু নয়, 0 নয় So তবে, আপনি যদি এতে পরিবর্তন করেন:
class Array;def avg;reduce(0.0,:+).try(:/,size);end;end
খালি অ্যারেগুলির ফলাফলটি আমার প্রত্যাশার মতো ব্যতিক্রম হবে না তবে পরিবর্তে এটি এনএএন ফেরায় ... আমি রুবিতে এর আগে কখনও দেখিনি। ;-) মনে হচ্ছে ভাসা শ্রেণীর একটি বিশেষ আচরণ ...
0.0/0 #==> NaN
0.1/0 #==> Infinity
0.0.class #==> Float
আমি গৃহীত সমাধান সম্পর্কে কি পছন্দ করি না
arr = [5, 6, 7, 8]
arr.inject{ |sum, el| sum + el }.to_f / arr.size
=> 6.5
এটি আসলে খাঁটি কার্যকরী উপায়ে কাজ করে না। শেষে arr.size গণনা করতে আমাদের একটি পরিবর্তনশীল আর্টের প্রয়োজন need
খাঁটি কার্যকরভাবে এটি সমাধান করার জন্য আমাদের দুটি মানের ট্র্যাক রাখতে হবে: সমস্ত উপাদানগুলির যোগফল এবং উপাদানের সংখ্যা।
[5, 6, 7, 8].inject([0.0,0]) do |r,ele|
[ r[0]+ele, r[1]+1 ]
end.inject(:/)
=> 6.5
সংথোষ এই সমাধানটির উন্নতি করেছে: যুক্তিটি আরে অ্যারের পরিবর্তে, আমরা এটিকে তাত্ক্ষণিকভাবে দুটি ভেরিয়েবলে পৃথক করে তুলতে কাঠামোগত ব্যবহার করতে পারি
[5, 6, 7, 8].inject([0.0,0]) do |(sum, size), ele|
[ sum + ele, size + 1 ]
end.inject(:/)
এটি কীভাবে কাজ করে তা যদি আপনি দেখতে চান তবে কিছু পুট যুক্ত করুন:
[5, 6, 7, 8].inject([0.0,0]) do |(sum, size), ele|
r2 = [ sum + ele, size + 1 ]
puts "adding #{ele} gives #{r2}"
r2
end.inject(:/)
adding 5 gives [5.0, 1]
adding 6 gives [11.0, 2]
adding 7 gives [18.0, 3]
adding 8 gives [26.0, 4]
=> 6.5
আমরা যোগফল এবং সংখ্যা গণনা করতে অ্যারের পরিবর্তে একটি কাঠামোও ব্যবহার করতে পারি, তবে তারপরে প্রথমে আমাদের স্ট্রাক্টটি ঘোষণা করতে হবে:
R=Struct.new(:sum, :count)
[5, 6, 7, 8].inject( R.new(0.0, 0) ) do |r,ele|
r.sum += ele
r.count += 1
r
end.inject(:/)
end.method
রুবীতে ব্যবহৃত দেখি , এর জন্য ধন্যবাদ!
arr.inject([0.0,0]) { |(sum, size), el| [ sum + el, size + 1 ] }.inject(:/)
পাবলিক বিনোদন, আরও একটি সমাধান:
a = 0, 4, 8, 2, 5, 0, 2, 6
a.reduce [ 0.0, 0 ] do |(s, c), e| [ s + e, c + 1 ] end.reduce :/
#=> 3.375
Array#average
।আমি প্রায়শই একই জিনিসটি করছিলাম তাই আমি ভেবেছিলাম কেবল Array
একটি সাধারণ average
পদ্ধতিতে ক্লাসটি প্রসারিত করা বুদ্ধিমান । এটি পূর্ণসংখ্যার বা ভাসমান বা দশমিকের মতো সংখ্যার অ্যারের ছাড়াও কোনও কিছুর জন্য কাজ করে না তবে আপনি যখন এটি সঠিকভাবে ব্যবহার করেন তখন তা কার্যকর।
আমি রুবেলগুলিকে রেলগুলি ব্যবহার করছি তাই এটি আমি রেখেছি config/initializers/array.rb
তবে আপনি এটি বুট ইত্যাদিতে যে কোনও জায়গায় রেখে দিতে পারেন can
config/initializers/array.rb
class Array
# Will only work for an Array of numbers like Integers, Floats or Decimals.
#
# Throws various errors when trying to call it on an Array of other types, like Strings.
# Returns nil for an empty Array.
#
def average
return nil if self.empty?
self.sum / self.size
end
end
a = [0,4,8,2,5,0,2,6]
sum = 0
a.each { |b| sum += b }
average = sum / a.length
a = [0,4,8,2,5,0,2,6]
a.empty? ? nil : a.reduce(:+)/a.size.to_f
=> 3.375
শূন্য, পূর্ণসংখ্যার বিভাগ দ্বারা বিভাজন সমাধান করে এবং পড়া সহজ। আপনি যদি খালি অ্যারে রিটার্ন 0 পছন্দ করেন তবে সহজেই পরিবর্তন করা যায়।
আমি এই বৈকল্পিকটিও পছন্দ করি তবে এটি আরও কিছুটা শব্দময়।
a = [0,4,8,2,5,0,2,6]
a.empty? ? nil : [a.reduce(:+), a.size.to_f].reduce(:/)
=> 3.375
arr = [0,4,8,2,5,0,2,6]
average = arr.inject(&:+).to_f / arr.size
# => 3.375
এই পদ্ধতিটি সহায়ক হতে পারে।
def avg(arr)
val = 0.0
arr.each do |n|
val += n
end
len = arr.length
val / len
end
p avg([0,4,8,2,5,0,2,6])
[1,2].tap { |a| @asize = a.size }.inject(:+).to_f/@asize
সংক্ষিপ্ত কিন্তু উদাহরণ ভেরিয়েবল ব্যবহার করে
a_size = nil; [1,2].tap { |a| a_size = a.size }.inject(:+).to_f/a_size
উদাহরণ ভেরিয়েবল তৈরি না করে করব do
আপনি নিম্নলিখিত মত কিছু চেষ্টা করতে পারেন:
a = [1,2,3,4,5]
# => [1, 2, 3, 4, 5]
(a.sum/a.length).to_f
# => 3.0