I actively started re-learning ruby by solving challenge exercise from exercism and I thought I should write about the challenges I found a bit difficult and overcame. You can check out my profile on exercsim to see my progress.
The Ruby Array flatten method takes any deeply nested array (Multi-dimensional) and returns a non nested array using recursion. For example (open IRB[Interactive Ruby] in your terminal and run):
[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 algorithm for solving this problem looked like:
- Create a
FlattenArrayclass with a
- The class method accepts a single array parameter
- Create an emepty array
flattenedto hold the elements of the new array.
- Loop through the array argument
- Push each elements into
- Recursively push deeply nested array into
- Return the one-dimensional
Classes in Ruby are created by using the
class keyword, a
meaningful class name and the
class FlattenArray end
From my algorithm, the class has a class method
flattenedand 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).
class FlattenArray def self.flatten(array) end end
The next steps include;
- Creating the
- Loop through the
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 without mutating it). Pushing the elements of
arr into the
flattened array possible with the use of
.push method, but I'd be sticking with
<< (personal preference).
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.
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
.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
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 :)
Another feature I love about learning on exercism 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
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:
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, [[]]], -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, [], [4, []], 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
Exercism 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 is one language i really enjoy writing and has an amazing ecosystem