Skip to content

Instantly share code, notes, and snippets.

@mharris717
Created February 18, 2010 22:50
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 mharris717/308173 to your computer and use it in GitHub Desktop.
Save mharris717/308173 to your computer and use it in GitHub Desktop.
# Putting the method on Array, instead of Enumerable, because I don't want hashes to flatten.
# There are other "flattenable" structures aside from an Array, but I am ignoring that.
class Array
# A structure is defined as "flattenable" if it responds to my_flatten
def my_flatten
res = []
each do |obj|
if obj.respond_to?(:my_flatten)
res.concat(obj.my_flatten)
else
res << obj
end
end
res
end
# Another implementation
# This is a somewhat strange use of inject, since it is using concat and <<
# (both of which modify the object they are called on) for the fact that
# they return that same object. However, I believe using them
# is more efficient than the alternative, something like
# res + obj.my_flatten_with_inject and res + [obj]
def my_flatten_with_inject
inject([]) do |res,obj|
if obj.respond_to?(:my_flatten_with_inject)
res.concat(obj.my_flatten_with_inject)
else
res << obj
end
end
end
end
require 'rubygems'
require 'spec'
# Not a complete set of specifications, but covers a good amount of cases.
context 'my_flatten' do
it 'empty' do
[].my_flatten.should == []
end
it 'one element' do
[1].my_flatten.should == [1]
end
it 'one array' do
[[1]].my_flatten.should == [1]
end
it 'one empty array' do
[[]].my_flatten.should == []
end
it 'two elements' do
[1,2].my_flatten.should == [1,2]
end
it 'an element and an array' do
[1,[2,3]].my_flatten.should == [1,2,3]
end
it 'an array within an array' do
[1,[[2,3],4]].my_flatten.should == [1,2,3,4]
end
it 'an empty array mixed with elements and full arrays' do
[1,2,[3,4],[],5].my_flatten.should == [1,2,3,4,5]
end
it 'a hash within the array' do
[1,2,{3 => 4},5].my_flatten.should == [1,2,{3 => 4},5]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment