Reinventing ruby flatten method
Published: 2019-05-17 10:30:43

---
title: Reinventing ruby flatten method
published: true
description:
tags: ruby,exercism,problem-solving, tdd, arrays, beginners
---
![Flattening a human](https://raw.githubusercontent.com/OPARA-PROSPER/Technical-Articles/master/git-backend/img/flatten.jpeg?token=AHGMCDH5R2WYFKEEAQ7Y6RC447BZC)

### Introduction

I actively started re-learning ruby by solving challenge exercise from [exercism](https://exercism.io) and I thought I should write about the challenges I found a bit difficult and overcame. You can check out [my profile](https://exercism.io/profiles/OPARA-PROSPER) on exercsim to see my progress.


### Problem statement

The Ruby Array flatten method takes any deeply nested array (Multi-dimensional) and returns a non nested array using [recursion](https://www.geeksforgeeks.org/recursion/). For example (open IRB[Interactive Ruby] in your terminal and run):

```ruby
[1,[[3,4,6],3,7],5,1,[1,2,3],5].flatten
# => [1, 3, 4, 6, 3, 7, 5, 1, 1, 2, 3, 5]
```

This challenge exercise requires that I write my personal implementation of the method, without using the method.

### My Implementation

My algorithm for solving this problem looked like:


- Create a `FlattenArray` class with a `flatten` class method
- The class method accepts a single array parameter `arr`
- Create an emepty array `flattened` to hold the elements of the new array.
- Loop through the array argument `arr`
- Push each elements into `flattened`
- Recursively push deeply nested array into `flattened`
- Return the one-dimensional `flattened` array

Classes in Ruby are created by using the `class` keyword, a `meaningful class name` and the `end` keyword.

```ruby
class FlattenArray
end
```
From my algorithm, the class has a class method `flattened`and accepts a single parameter/argument. In Ruby, the `self` keyword is used for creating class methods (class methods are methods that belong to the class it was created in and not instances (objects) of the class).

```ruby
class FlattenArray
  def self.flatten(array)
  end
end
```
The next steps include;
- Creating the `flattened` array
- Loop through the `arr` parameter
- Push `arr` elements into `flattened` array

For looping through the array parameter, we'd utilize the `each` iterator (this loops through all the elements within an array, and allows you do manipulate the elements within a code block, and it additionally returns the original [Enumerator](https://ruby-doc.org/core-2.2.0/Enumerator.html) without mutating it). Pushing the elements of `arr` into the `flattened` array possible with the use of  `<<` or `.push` method, but I'd be sticking with `<<` (personal preference).

```ruby
class FlattenArray
  def self.flatten(arr)
    flattened = []
    arr.each do |element|
      flattened << element
    end
  end
end
```

The next step involves adding a call to the `flatten` method within itself(this is called recursion) tp keep us from unnecessary nested iterations in cases of multi-dimensional array arguments.

```ruby
class FlattenArray
  def self.flatten(arr)
    flattened = []
    arr.each do |element|
      if element.is_a? Array
        flattened.concat(flatten(element))
      else
        flattened << element
      end
    end
    flattened
  end
end
```
My initial challenge was using `<<` to push into the flattened array, which actually push an array object into  `flattened`. Using `.concat` method on the other hand **appends** each element from the iteration into `flattened` instead of pushing an array object. Testing manually to check if this implemetatio works 

```ruby
print FlattenArray::flatten [1,2,3,[[3,4],6,6]]
```

> Omitting the parenthesis in a method call is allowable in ruby and correct ruby syntax. Also, I personally enjoy calling functions without parenthesis :)

### Testing 

Another feature I love about learning on [exercism](https://exercism.io) is that you'd solve the exercises using Test Driven Development(TDD) methodology and it's really cool I must say. Writing Test Suites in ruby requires that you have `minitest` gem installed, you can install minitest using the `gem install` command:

```
$ gem install minitest
```

Create a `flatten_test.rb` file in the same directory with flatten.rb (File for our flatten implementation code), in the newly created file require the *minitest* gem, require *flatten.rb* (using `require_relative`) and copy the following Test Suite:

```ruby
require 'minitest/autorun'
require 'minitest/pride'
require_relative 'flatten_array'

# Common test data version: 1.2.0 0290376
class FlattenArrayTest < Minitest::Test
  def test_no_nesting
    # skip
    flat_array = FlattenArray.flatten([0, 1, 2])
    assert_equal [0, 1, 2], flat_array
  end

  def test_flattens_array_with_just_integers_present
    # skip
    flat_array = FlattenArray.flatten([1, [2, 3, 4, 5, 6, 7], 8])
    assert_equal [1, 2, 3, 4, 5, 6, 7, 8], flat_array
  end

  def test_5_level_nesting
    # skip
    flat_array = FlattenArray.flatten([0, 2, [[2, 3], 8, 100, 4, [[[50]]]], -2])
    assert_equal [0, 2, 2, 3, 8, 100, 4, 50, -2], flat_array
  end

  def test_6_level_nesting
    # skip
    flat_array = FlattenArray.flatten([1, [2, [[3]], [4, [[5]]], 6, 7], 8])
    assert_equal [1, 2, 3, 4, 5, 6, 7, 8], flat_array
  end
```

Make sure to un-comment the `skip` keyword within each test to enable the test code run and avoid **skipping** that test case. You can now run the command below in terminal:

```
$ ruby flatten_test.rb
```
To learn more about writing test in ruby, read [intro to TDD](http://tutorials.jumpstartlab.com/topics/testing/intro-to-tdd.html#intro-to-tdd)

### Wrap up

[Exercism](https://exercism.io) is an amazing tool for learning any programming language of your choice and also get mentorship while working on your solution. Exercism mentors don't hand you the fish, rather they give you the fish hook and tell you the coordinates of the fish, this totally makes fishing fun, research oriented and fast.

If you followed the code implementation from beginning to end, you must have discovered how awesome the Ruby programming language is and how lienient the syntax is, [Ruby](https://ruby-doc.org/) is one language i really enjoy writing and has an amazing [ecosystem](http://ruby-forum.com/)