Ruby make list minimum length

In a Ruby on Rails app, I wanted a list to be at least of two items. This could be done in several ways.

Here is a first naïve impementation:

# Naïve implementation, just return whatever number I need def sum_up_a(existing) return 2 if existing == 0 return 1 if existing == 1 return 0 end sum_up_a(0) # => 2 sum_up_a(1) # => 1 sum_up_a(2) # => 0 sum_up_a(3) # => 0 sum_up_a(10) # => 0

A slightly improved version could investigate number of existing, and return the diff only if needed:

MIN_COUNT = 2 # slightly improved with less conditionals def sum_up_b(existing) return 0 if existing >= MIN_COUNT MIN_COUNT - existing end sum_up_b(0) # => 2 sum_up_b(1) # => 1 sum_up_b(2) # => 0 sum_up_b(3) # => 0 sum_up_b(10) # => 0

 

Now, my favourite. If you look at the result of “MIN_COUNT – existing”. This number is negative or zero if we dont want extra rows. This means that we can rewrite the algorithm without any conditional logic like this:

# my favorite: return the biggest number either 0 or the difference # Works well because difference is only positive for numbers where I # need some extra rows def sum_up_c(existing) [MIN_COUNT - existing, 0].max end sum_up_c(0) # => 2 sum_up_c(1) # => 1 sum_up_c(2) # => 0 sum_up_c(3) # => 0 sum_up_c(10) # => 0

I like the latter, since too many conditional statements tend to clutter the logic. Just a short tip and a reminder for myself next time I run into this kind of problem.

 

Complete example gist avalilable on Github:

2 Responses to “Ruby make list minimum length”

  1. Jakob S Says:

    I’d argue the first, naive implementation is the optimal one. Sure, option C might be clever, but I couldn’t tell you what it does without running the code in my head. Clever is rarely a quality to aim for: https://medium.com/@mikesherov/writing-clear-code-not-clever-code-d6b90353a3c5#.rkedlie16 ;)

    If you don’t like the return statements you could go for a case statement instead:

    def sum_up_case(existing)
    case existing
    when 0
    2
    when 1
    1
    else
    0
    end
    end

    or potentially a lookup table if the above is too verbose:

    def sum_up_lookup(existing)
    {
    0 => 2,
    1 => 1
    }.fetch(existing, 0)
    end

  2. Jesper Says:

    I gonna pass this link to my colleague, who strugles with sort of same problem