-1

How can I write a Ruby function that can calculate the average of an array? If the array doesn't have any elements, the result should be 0. I should use a loop for the implementation. I started like this, but I'm not quite sure how to use the loop.

a = [1, 2, 3, 4, 5, 6]

def average(a)  
  sum = 0.0
  result = 0.0
  if array.length > 0 then
    array.each do |item|
      sum += item
    end
    result = sum / array.length
  end
  return result.to_f
end
sawa
  • 165,429
  • 45
  • 277
  • 381
  • 1
    Possible duplicate of [How do I create an average from a Ruby array?](https://stackoverflow.com/questions/1341271/how-do-i-create-an-average-from-a-ruby-array) – Sebastián Palma Dec 15 '18 at 16:51
  • The only difference is you're trying to wrap the average calculation in a method. – Sebastián Palma Dec 15 '18 at 16:51
  • I'm confused... what does that mean 'trying to wrap the average calculation in a method'? –  Dec 15 '18 at 16:55
  • About your question and the possible duplicate. – Sebastián Palma Dec 15 '18 at 17:02
  • _"I should use a loop"_ – could you be more specific? What qualifies as a loop? – Stefan Dec 15 '18 at 17:29
  • I can't be more specific thats just what my prof told us to include. –  Dec 15 '18 at 17:44
  • If you can't be more specific, then we cannot answer your question. How can we tell you what it looks like to "use a loop" if you can't tell us what "use a loop" means? For example, in your code, there is nothing that I would call a "loop". Also, it makes no sense to use a loop for this. The entire code is just `def average(a) return 0 if a.empty?; a.sum.fdiv(a.size) end`. – Jörg W Mittag Dec 15 '18 at 17:47
  • I know that's what was confusing me ... –  Dec 15 '18 at 17:50
  • 3
    If your exercise instructions are confusing, the most likely person to help you, is the person who gets paid to make sure your exercise instructions are not confusing, i.e. your TA / instructor / teacher / professor. Random anonymous people on the interwebs cannot really read your instructor's mind, I'm afraid. When I was confronted with exercises like this, I would simply solve them several different ways, e.g. with a library method, a higher-order function, tail-recursion, and a loop, and then discuss the pros and cons of those 4 approaches. – Jörg W Mittag Dec 15 '18 at 17:52
  • That makes sense... I was translating the exercise so I'm not quite sure if that's the reason I can't be more specific. –  Dec 15 '18 at 17:56
  • What is `array`? – sawa Dec 17 '18 at 04:18

4 Answers4

1
def average(arr, precision=0)
  return 0 if arr.empty?
  arr.sum.fdiv(arr.size).round(precision)
end

arr = [1,2,3,7]

average(arr)   #=> 3
average(arr,2) #=> 3.25

Rather than using Integer#fdiv you could write

(arr.sum.to_f/arr.size).round(precision)
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
0

I suppose we can also write it simply as below

a = [1, 2, 3, 4, 5, 6]
def average(arr=[])  
  sum = 0.0
  i=0
  while(i < arr.length) do
    sum += arr[i].to_f
    i += 1
  end
  return ((i==0) ? 0 : (sum / i))
end

We can loop and calculate sum this way. Afterwards for average we took value of i which will be retained value after loop and make conditional operator for returning result.

Its simple solution, I have not tested it though so can have mistakes. You can try on your side. Hope This helps !!

Mayank
  • 727
  • 6
  • 9
  • Thank you for your help! Which function does the 'i = 0' have? –  Dec 15 '18 at 18:16
  • just a measure that 'i' will not be local to the while loop and will be available outside plus it initializes the variable. Did I get your question here? – Mayank Dec 15 '18 at 18:18
  • Yes I think I get it now. Can you maybe explain why you used '?' in the return-part? –  Dec 15 '18 at 18:24
  • its a conditional operator ? : which is like if..else..end block in short. It is used to prevent devide-by-zero error if 'i' is 0. It says if 'i' is 0 then return 0 else divide sum by 'i' to get average which will be float as sum is in decimals. – Mayank Dec 15 '18 at 18:28
  • If you want more info on the conditional operator (also called ternary operator), this is a good answer on SO: https://stackoverflow.com/a/4252945/249353 – Josien Dec 15 '18 at 21:02
  • This is one of the many reasons I dislike the conditional operator. What's wrong with a conditional expression here? `return if i.zero? then 0 else sum / i end` (Actually, in both cases, the `return` is superfluous and non-idiomatic.) – Jörg W Mittag Dec 16 '18 at 08:33
  • Note: using the `do` keyword in multi-line loops non-idiomatic. Using parentheses around the condition is non-idiomatic. Using no whitespace around binary operators is non-idiomatic. – Jörg W Mittag Dec 16 '18 at 08:35
  • Ok Noted @JörgWMittag. One request can you please update the code above. Thanks – Mayank Dec 16 '18 at 19:28
0

You can write this:

def average(values)
    total = 0.0

    values.each do |i| 
        total += i
    end

    return total / values.length()
end

If you want to use a loop, you can do it this way:

def average(values=[])
    total = 0.0

    for i in values
        total += i
    end

    return total / values.length()
end

If a non-empty array is passed, it will return the average of the values. If an empty array is passed, it will return 0.0.

You can test it like this:

puts average([1, 2, 3, 4, 5]) #=> "3"
puts average([]) #=> "0"
Pika Supports Ukraine
  • 3,612
  • 10
  • 26
  • 42
0
def average(a)
  if a.empty?
    0
  else
    sum = a.inject(0.0){|x, sum| sum += x}
    sum / a.size.to_f
  end
end
Gregory Ostermayr
  • 1,123
  • 10
  • 17