Skip to content

Instantly share code, notes, and snippets.

@MikeRogers0
Last active May 23, 2016 21:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MikeRogers0/c9cdc79b2632448b155f308a668448d4 to your computer and use it in GitHub Desktop.
Save MikeRogers0/c9cdc79b2632448b155f308a668448d4 to your computer and use it in GitHub Desktop.
Some code, that will flatten an array of arbitrarily nested arrays of integers into a flat array of integers. e.g. [[1,2,[3]],4] -> [1,2,3,4].

For Citrusbyte.

I wrote these two methods using Ruby 2.3.1, the tests require the minitest gem to be installed on your system.

You can run the tests using the command

ruby flatten_recursion_test.rb ruby flatten_regex_test.rb

Here is a summary of the two methods:

[].flatten_with_recursion - I googled the question and found a solution that used recursion, though if the array is deep enough it will throw a SystemStackError error.

[].flatten_with_regex - I thought it would be fun to use gsub to solve the problem. This approach does not throw a SystemStackError error when the array is very deep.

require "minitest/autorun"
require "flatten_with_recursion"
class TestFlattenWithRecursion < Minitest::Test
def test_flattens_an_array_of_arbitrarily_nested_arrays_of_integers_into_a_flat_array_of_integers
flattened_array = [[1,2,[3]],4].flatten_with_recursion
assert_equal [1,2,3,4], flattened_array
end
def test_flattens_an_empty_array
flattened_array = [].flatten_with_recursion
assert_equal [], flattened_array
end
def test_unable_to_flatten_a_very_nested_array
skip "This will fire a SystemStackError: stack level too deep because we used recursion"
silly_array = [3]
# This is a very deep array, it will cause a stack level to deep error
8192.times do
silly_array = [silly_array]
end
flattened_array = silly_array.flatten_with_recursion
assert_equal 3, flattened_array
end
end
# http://careers.citrusbyte.com/apply/tPTZOv/Experienced-Backend-Engineer
# This is the regex approach to flattening an array.
#
# I doubt you'd realistically use this solution in production, but I
# wanted to find a solution that wasn't on StackOverflow
class Array
def flatten_with_regex
self
.to_s # This turns the array into: "[[1,2,[3]],4]"
.gsub(/[\[|\]]/ism, "") # Remove those brackets, so it's now: "1,2,3,4"
.split(", ") # Now rejoin into a single array: ["1","2","3","4"]
.map(&:to_i) # Convert all items in array back to integers: [1,2,3,4]
end
end
require "minitest/autorun"
require "flatten_regex"
class TestFlattenWithRegex < Minitest::Test
def test_flattens_an_array_of_arbitrarily_nested_arrays_of_integers_into_a_flat_array_of_integers
flattened_array = [[1,2,[3]],4].flatten_with_regex
assert_equal [1,2,3,4], flattened_array
end
def test_flattens_an_empty_array
flattened_array = [].flatten_with_regex
assert_equal [], flattened_array
end
def test_can_flatten_a_very_nested_array
silly_array = [3]
8192.times do
silly_array = [silly_array]
end
flattened_array = silly_array.flatten_with_regex
assert_equal 3, flattened_array
end
end
# http://careers.citrusbyte.com/apply/tPTZOv/Experienced-Backend-Engineer
# This is the recursion approach
#
# I quickly googled the question and found http://stackoverflow.com/questions/31940239/flatten-a-ruby-array-without-using-built-in-flatten-method
# It seemed like a pretty nice solution, but here it is annotated.
class Array
# Monkey patch the flatten_with_recursion to the Array class
def flatten_with_recursion
# itterate over the first level of items in the array.
# each_with_object starts as [], then anything added to it during the loop persists and is returned
each_with_object([]) do |element, new_array|
if element.is_a?(Array)
# When the object is an array, splat the array and push to new_array as single arguments.
# This will pretty much turn:
# new_array.push *[1,2,3,4]
# into
# new_array.push 1,2,3,4
new_array.push *element.flatten_with_recursion
else
new_array.push element
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment