Ever wanted an integer to be allowed a specific range of valid numbers rounding when necessary? Well, unfortunately in the Ruby community this has been a point of contention because no built-in function exists. We can however easily replicate the intended behavior through the clever usage of the enumerable sort method.

This may be a bit overkill...

Image property of amazon.com

Image property of amazon.com

Because we want to return an integer that has been "clamped" to a specific range we need a way to set a minimum and maximum value. The Enumerable sort method comes in handy for this purpose. We'll be using the sort method while grabbing the second element in the returned array to gather the appropriate clamp value.

All about sort

Enumerable#sort takes an array and attempts to sort the elements either alphabetically or by number unless a custom sort is passed to the block. This allows something like the following to occur.

%w(rhea kea flea).sort     #=> ["flea", "kea", "rhea"]

Sort Defined:
"Returns an array containing the items in enum sorted, either according to their own <=> method, or by using the results of the supplied block."

For the sake of this post we will use the following integer range of 0 to 10 to set the min and max values. These values will use the sort method to order them in rising order. I will show a couple examples below to demonstrate how this method works.

x = 20
[x, 0, 10].sort[1]  #=> 10

x = -10
[x, 0, 10].sort[1]  #=> 0

x = 6
[x, 0, 10].sort[1]  #=> 6

x = 10
[x, 0, 10].sort[1]  #=> 10

Pretty slick looking, albeit a bit cryptic. Never fear it is actually quite simple to explain.

By using three integers, one of which is our input integer, and then calling sort on them we receive the integers in rising order from lowest to smallest. The trick here is .sort[1]. This says sort the previous array and return the 2nd element from it. Since arrays start at 0 then [1] means the second or middle element.

Clamp Equation:
[x, a, b].sort[1]

x - input
a - minimum value
b - maximum value

Disassemble it!

Image property of http://genius.com/

Image property of http://genius.com/

So now we will always return the proper clamped value. Lets take a look at an example of what is happening. I'll reuse the first example from above with comments to disassemble what is happening in the intermediate steps.

# Usage
x = 20
[x, 0, 10].sort[1]

# Explanation
[x, 0, 10]
# [20, 0, 10]  This is what the array looks like in reality

[20, 0, 10].sort
# [0, 10, 20]  What the array looks like after the sort method is called

[0, 10, 20].sort[1]
# .sort[1] returns 10 because 10 is the second index in the array

There you have it. A simple and easy way to clamp integers between a range. Also you might be wondering why I keep using the phrase clamp. That is because in other programming languages the clamp method is built-in to accomplish this from the start.

TL;DR

Here it is in method form for easy copy and pasting.

def clamp (input, min, max)
    [input, min, max].sort[1]
end

Join the conversation

comments powered by Disqus