Skip to content

Instantly share code, notes, and snippets.

@habibalamin
Created June 30, 2017 21:49
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 habibalamin/ce5d042f061dae78161ba41c6e46dbb0 to your computer and use it in GitHub Desktop.
Save habibalamin/ce5d042f061dae78161ba41c6e46dbb0 to your computer and use it in GitHub Desktop.
--require ./deepflat_spec
--format documentation
--color
module Deepflat
refine Array do
# Duplicating the array before mutating
# it is less space efficient, but a lot
# safer. This shouldn't be a problem if
# you are not working with huge arrays.
#
# An alternative approach is recursion,
# which can cause a stack overflow with
# too deeply nested arrays.
#
# I show both solutions here.
def deep_flatten_iterative
[].tap do |accumulator|
remaining = dup
while remaining.count > 0 do
element = remaining.shift
if element.is_a?(Array)
remaining = element + remaining
next
else
accumulator << element
next
end
end
end
end
# Thwart stack overflows by letting the
# Ruby VM do tail call optimisation and
# change the recursive call into a tail
# recursive call. To be honest, I don't
# know if that'll work if the recursive
# call is to another object.
def deep_flatten_recursive
reduce([]) do |accumulator, element|
if element.is_a?(Array)
accumulator + element.deep_flatten_recursive
else
accumulator + [element]
end
end
end
end
end
require_relative 'deepflat'
RSpec.describe Deepflat do
using Deepflat
describe '#deep_flatten_iterative' do
it 'should flatten [] to []' do
expect([].deep_flatten_iterative).to eq []
end
it 'should flatten [[[]], []] to []' do
expect([[[]], []].deep_flatten_iterative).to eq []
end
it 'should flatten [1] to [1]' do
expect([1].deep_flatten_iterative).to eq [1]
end
it 'should flatten [1, 2, 3, 4] to [1, 2, 3, 4]' do
expect([1, 2, 3, 4].deep_flatten_iterative).to eq [1, 2, 3, 4]
end
it 'should flatten [[1, 2, [3]], 4] to [1, 2, 3, 4]' do
expect([[1, 2, [3]], 4].deep_flatten_iterative).to eq [1, 2, 3, 4]
end
it 'should flatten [[1, 2, [[3]]], 4] to [1, 2, 3, 4]' do
expect([[1, 2, [[3]]], 4].deep_flatten_iterative).to eq [1, 2, 3, 4]
end
it 'should flatten [1, [2, 3, [[4]]], 5] to [1, 2, 3, 4, 5]' do
expect([1, [2, 3, [[4]]], 5].deep_flatten_iterative).to eq [1, 2, 3, 4, 5]
end
it 'should flatten [1, [2, 3], [4, [5]], 6] to [1, 2, 3, 4, 5, 6]' do
expect([1, [2, 3], [4, [5]], 6].deep_flatten_iterative).to eq [1, 2, 3, 4, 5, 6]
end
end
describe '#deep_flatten_recursive' do
it 'should flatten [] to []' do
expect([].deep_flatten_recursive).to eq []
end
it 'should flatten [[[]], []] to []' do
expect([[[]], []].deep_flatten_recursive).to eq []
end
it 'should flatten [1] to [1]' do
expect([1].deep_flatten_recursive).to eq [1]
end
it 'should flatten [1, 2, 3, 4] to [1, 2, 3, 4]' do
expect([1, 2, 3, 4].deep_flatten_recursive).to eq [1, 2, 3, 4]
end
it 'should flatten [[1, 2, [3]], 4] to [1, 2, 3, 4]' do
expect([[1, 2, [3]], 4].deep_flatten_recursive).to eq [1, 2, 3, 4]
end
it 'should flatten [[1, 2, [[3]]], 4] to [1, 2, 3, 4]' do
expect([[1, 2, [[3]]], 4].deep_flatten_recursive).to eq [1, 2, 3, 4]
end
it 'should flatten [1, [2, 3, [[4]]], 5] to [1, 2, 3, 4, 5]' do
expect([1, [2, 3, [[4]]], 5].deep_flatten_recursive).to eq [1, 2, 3, 4, 5]
end
it 'should flatten [1, [2, 3], [4, [5]], 6] to [1, 2, 3, 4, 5, 6]' do
expect([1, [2, 3], [4, [5]], 6].deep_flatten_recursive).to eq [1, 2, 3, 4, 5, 6]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment