Created
June 30, 2017 21:49
-
-
Save habibalamin/ce5d042f061dae78161ba41c6e46dbb0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--require ./deepflat_spec | |
--format documentation | |
--color |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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