简体   繁体   中英

How to get the minimum value of an array, based on comparing more than one block using min_by?

Given this example array of numbers:

sizes = [35, 40, 45, 50, 55, 60]

And this required size to fit:

fit_this = 30

I want to find the minimum size based on these given blocks:

sizes.min_by { |size| (size - fit_this).abs }   #=> 35
sizes.min_by { |size| (size - fit_this*2).abs } #=> 60

The sizes are widths, and I'm trying to put as many fit_this items into the width with the least amount of wasted space, so the fit_this number can be doubled up if it's a better fit.

Is it possible to do this with min_by ? If not, what's the best way to do it in Ruby?

Let's examine the intermediate arrays by replacing min_by with map :

sizes.map { |size| (size - fit_this).abs }
#=> [5, 10, 15, 20, 25, 30]

sizes.map { |size| (size - fit_this*2).abs }
#=> [25, 20, 15, 10, 5, 0]

We can combine both calculations by returning element-wise arrays:

sizes.map { |size| [(size - fit_this).abs, (size - fit_this*2).abs] }
#=> [[5, 25], [10, 20], [15, 15], [20, 10], [25, 5], [30, 0]]

And use min to fetch the smaller number of each pair:

sizes.map { |size| [(size - fit_this).abs, (size - fit_this*2).abs].min }
#=> [5, 10, 15, 10, 5, 0]

Applied to min_by :

sizes.min_by { |size| [(size - fit_this).abs, (size - fit_this*2).abs].min }
#=> 60

Yes, we can do that.

The basic idea is we want to try for two cases for all sizes and choose what is the best fit:

sizes.min_by { |size| [(size - fit_this).abs, (size - fit_this * 2).abs].min }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM