Oli Plunkett
Oli Plunkett

Reputation: 87

Yielding a modified Ruby array to a block

I'm trying to turn 2 lines of ruby code into 1. For example:

def average(numbers)
  result = numbers.compact
  numbers.reduce(+) / numbers.length
end

I've been looking through array methods and can't find an appropriate one to turn this function into a one-liner. I had hoped something like this would work:

def average(numbers)
  numbers.compact.<tap or another method> { |arr| arr.reduce(+) / arr.length }
end

Basically, I'm modifying the array (in the example I have to call compact to rid nil values), so I don't have access to the array variable, and I don't want an iterator, because I don't want to call reduce(+) and length on individual elements of the array.

Does anyone have an idea of methods I could look into?

Upvotes: 0

Views: 56

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110685

I believe you mean for your method to be the following (reduce(:+), not reduce(+) and use result rather than numbers in the second line).

def average(numbers)
  result = numbers.compact
  result.reduce(:+) / result.length
end

average [1,2,3]
  #=> 2

If you wish the average to be a float, change the second line to

result.reduce(0.0, :+) / result.length

There are various ways to combine the two lines of the method, but I don't prefer any of them to the above. Here are a few. (I don't see how Object#tap could be used here.)

numbers.compact.reduce(:+) / numbers.compact.length

(result = numbers.compact).reduce(:+) / result.compact.length

numbers.map(&:to_i).reduce(:+) / numbers.compact.length

Note that, even if numbers can be mutated, one cannot write

numbers.compact!.reduce(:+) / numbers.length

because numbers.compact! returns nil if numbers contains no nil elements.

In Ruby v2.4+ you can use Array#sum:

result.sum / result.length

Upvotes: 2

seph
seph

Reputation: 6076

You could change the way you call average

def average(numbers)
  numbers.reduce(:+) / numbers.length
end

average(num_array.compact)

Upvotes: 0

Related Questions