Skip to content

Instantly share code, notes, and snippets.

@allolex
Last active February 27, 2020 22:17
Show Gist options
  • Save allolex/4325f83cde7e987f1ada0bd10879def2 to your computer and use it in GitHub Desktop.
Save allolex/4325f83cde7e987f1ada0bd10879def2 to your computer and use it in GitHub Desktop.
Small code sample to demonstrate the implementation of an array flattening algorithm in Ruby

Flattenable

Extend your classes to flatten list-like objects that contain other lists and integers.

Synopsis

require_relative "flattenable"

class MyFlattener
  extends Flattenable
end

MyFlattener.flatten(
  [1, [2], [3, [4]]]
)

#=> [1, 2, 3, 4]

Testing

Run in documentation format:

rspec -fdoc flattenable_spec.rb

# Flattens lists containing lists and integers
# Works with list-like objects via duck typing
module Flattenable
def flatten(list_to_flatten)
unless self.list_type?(list_to_flatten)
raise ArgumentError, "Argument must be a list type"
end
list_to_flatten.inject([]) do |flattened_list, item|
if self.list_type?(item)
flattened_list.concat(self.flatten(item))
else
unless item.is_a?(Integer)
raise ArgumentError, "Argument list may contain only integers"
end
flattened_list << item
end
end
end
protected
def list_type?(value)
value.respond_to?(:each) and not value.respond_to?(:keys)
end
end
require "rspec"
require_relative "flattenable"
class Flattener
extend Flattenable
end
RSpec.describe Flattener do
it "flattens correctly with the provided example" do
expect(described_class.flatten( [[1, 2, [3]], 4])).to eq([1, 2, 3, 4])
end
it "flattens correctly with deep nesting" do
expect(described_class.flatten( [0, [1, [2, [3, [4]]]]])).to eq([0, 1, 2, 3, 4])
end
it "flattens correctly with simple lists" do
expect(described_class.flatten([1])).to eq([1])
end
it "fails when given a list of characters" do
expect{ described_class.flatten(["a"]) }.to raise_error(ArgumentError, /contain only integers/)
end
it "fails when given a hash type" do
expect{ described_class.flatten({a: 1}) }.to raise_error(ArgumentError, /must be a list/)
end
it "fails when given a hash type inside a list" do
expect{ described_class.flatten([1, {a: 1}]) }.to raise_error(ArgumentError, /contain only integers/)
end
it "fails when given an integer outside of a list" do
expect{ described_class.flatten(1) }.to raise_error(ArgumentError, /must be a list/)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment