Skip to content

Instantly share code, notes, and snippets.

@tgaff
Last active September 19, 2016 23:27
Show Gist options
  • Save tgaff/2940ba5619408e7444e381e71baf47a2 to your computer and use it in GitHub Desktop.
Save tgaff/2940ba5619408e7444e381e71baf47a2 to your computer and use it in GitHub Desktop.
flatten array
source "https://rubygems.org"
gem "rspec"
# File location: spec/spec_helper.rb
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
# This option will default to `true` in RSpec 4. It makes the `description`
# and `failure_message` of custom matchers include text for helper methods
# defined using `chain`, e.g.:
# be_bigger_than(2).and_smaller_than(4).description
# # => "be bigger than 2 and smaller than 4"
# ...rather than:
# # => "be bigger than 2"
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
config.warnings = true
# Many RSpec users commonly either run the entire suite or an individual
# file, and it's useful to allow more verbose output when running an
# individual spec file.
if config.files_to_run.one?
# Use the documentation formatter for detailed output,
# unless a formatter has already been configured
# (e.g. via a command-line flag).
config.default_formatter = 'doc'
end
config.order = :random
Kernel.srand config.seed
end
# File location: lib/Utils.rb
module Utils
# flattens nested arrays into one shallow array [[2], [[1,3]]] -> [2,1,3]
def flatten(arr)
results = []
arr.each do |element|
# if element is an Array - flatten it and push each returned element into results
if element.is_a?(Array)
flatten(element).each { |sub_element| results.push(sub_element) }
else
results.push(element)
end
end
results
end
end
# File location: spec/utils_spec.rb
require 'Utils'
include Utils
RSpec.describe 'flatten' do
let(:shallow_array) { [0,3,5,7,9] }
it "returns an array" do
expect(flatten([2, 3])).to be_an(Array)
end
it "returns an empty array when given an empty array" do
expect(flatten([])).to eq([])
end
context 'when the array is entirely shallow' do
it "returns the original array" do
expect(flatten(shallow_array)).to eq shallow_array
end
end
context 'when the array is deep' do
it "de-nests a single nested array" do
expect(flatten( [0, [1,2], 3] )).to eq [0, 1, 2, 3]
end
it "de-nests a single-deep array with multiple nested arrays" do
expect(flatten( [0, [1,2], [3,4], 5, 6] )).to eq [0, 1, 2, 3, 4, 5, 6]
end
it "de-nests multiple deeply nested arrays" do
# note, you might do these as 'let' statements like above, but since we only use them once that
# would unnecessarily separate our test objects from test code
really_deep = [0, [1, [2, [3], [4,5], [[[6], 7]]], [8, 9]], 10, 11, [[12],[13], 14] ]
really_deep_flat = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
expect(flatten(really_deep)).to eq really_deep_flat
end
# edge-cases
it "de-nests multiply nested arrays when the nested element is the 0th element" do
expect(flatten([[[[0]]], 1])).to eq([0,1])
end
it "de-nests multiply nested arrays when the nested element is the .last element" do
expect(flatten([0, [[[[[[[1]]]]]]] ])).to eq([0,1])
end
it "drops empty nested arrays" do
expect(flatten([0, [], 2])).to eq [0,2]
end
end
end
@tgaff
Copy link
Author

tgaff commented Sep 19, 2016

overly clever shortened version:

  def flatten(arr)
    results = []
    arr.each { |element|  element.is_a?(Array) ? flatten(element).each(&results.method(:push)) : results.push(element) }
    results
  end

While this version is shorter - I prefer code that is easier to read and understand. That makes devs more productive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment