## DEV Community

Kevin Murphy for The Gnar Company

Posted on • Updated on • Originally published at blog.thegnar.co

# Code Golf: Conditionally Add To An Array

## The Grass Is Always Greener

We're building a system to track a golfer's statuses during a tournament. This is a competitive tournament with people who are much better than I will ever be, so if a golfer is currently scoring under par, they're in contention to win. On this 18 hole course, if they've played the first nine holes, they've made the turn.

Let's explore a number of ways we can build up an array that keeps track of which, if any, of these statuses a particular golfer qualifies for. Not content to settle for one that works, we'll dig into a variety of options.

## Teeing Up An Option

We can start with an empty array, and explicitly add in any of the statuses that the golfer meets the conditions for.

``````def current_statuses
statuses = []

if under_par?
statuses << "in_contention"
end

if back_nine?
statuses << "past_the_turn"
end

statuses
end
``````

There's nothing tremendously exciting here, and that's not a bad thing! It's reasonably clear what this is doing.

## Tapping It In

We can make the prior suggestion a little more terse by using tap.

``````def current_statuses
[].tap do |statuses|
if under_par?
statuses << "in_contention"
end

if back_nine?
statuses << "past_the_turn"
end
end
end
``````

This eliminates the need for the `statuses` temporary array from the prior section.

## Taking a Compact Swing

We can also build our array to have an entry for each of the conditionals we have, and removing the ones that aren't relevant.

``````def current_statuses
[
under_par? ? "in_contention" : nil,
back_nine? ? "past_the_turn" : nil,
].compact
end
``````

By using compact, we'll remove any `nil` values - and we'll take advantage of that functionality by explicitly adding `nil` if the golfer doesn't meet that condition.

## Working On Your Backswing Takeaway

Speaking of taking things away, we can also do the opposite of the first approach. We'll start by having each status, and then removing the ones that do not meet the necessary condition.

``````def current_statuses
statuses = ["in_contention", "past_the_turn"]

unless under_par?
statuses -= ["in_contention"]
end

unless back_nine?
statuses -= ["past_the_turn"]
end

statuses
end
``````

This may be more helpful in situations where there are a lot more statuses, and only a few of them may need to be removed for certain reasons. It may also help when the full list of statuses persists on its own elsewhere, but then you also need a subset of them in a particular case.

## Selecting The Right Club

Lastly, we'll put together a hash keyed on the statuses where the value is the result of the conditions. We can then flex some familiarity with Ruby's Enumerable module to pick out the applicable sections of the hash, returning only the statuses.

``````def current_statuses
{
"in_contention" => under_par?,
"past_the_turn" => back_nine?,
}.select { |_status, condition| condition }.keys
end
``````

Similar to the prior suggestion, this may be helpful when you want to have the full list of statuses and their associated conditions all compiled in one place, but then want to peel off which are relevant for a particular golfer at this time.

Here are some of the ways that we might solve this problem. What other ways could we build this functionality? Let me know what other approaches you would take.

This post originally published on The Gnar Company blog.

Nicolás Sanguinetti

In the spirit of golfing, using `filter_map` (ruby 2.7+) would make the hash version a bit shorter:

``````def current_statuses
{
"in_contention" => under_par?,
"past_the_turn" => back_nine?,
}.filter_map { |status, condition| status if condition }
end
``````

Felix Wolfsteller • Edited

``````def current_statuses
# this could also be done using inject
[] +
(under_par? ? %w{in_contention} : []) +
(back_nine? ? %w{past_the_turn} : [])
end
``````

(or use `['in_contention']` instead of `%w{in_contention}`).

Or with dynamic evaluation

``````def statuses
status_evals = {
:under_par? => 'in_contention',
:back_nine? => 'past_the_turn'
}

# could obviously be shortend by chaining
status_evals.select{|k,_v| method(k).call}.values
end
``````

Jon Randy 🎖️

Add here was me thinking this would be a post on Code Golf

Kevin Murphy

While not strictly focused on the fewest keystrokes to solve the problem, the ethos of finding multiple ways to solve the problem was definitely an inspiration, hence the reference.