Skip to content

Instantly share code, notes, and snippets.

@joshburgess
Last active February 10, 2018 17:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshburgess/82036f8c7aa036d04425692bae667fbd to your computer and use it in GitHub Desktop.
Save joshburgess/82036f8c7aa036d04425692bae667fbd to your computer and use it in GitHub Desktop.
Solutions showing how to flatten arbitrarily nested arrays of ints in JavaScript
// shorthand function for the Number.isInteger method
const isInt = Number.isInteger
// shorthand function for the Array.isArray method
const isArray = Array.isArray
// functional wrapper for the Array.reduce method
const reduce = f => initVal => arr => arr.reduce(f, initVal)
// functional wrapper for the Array.concat method
const concat = arrA => arrB => arrA.concat(arrB)
// functional composition utility
const compose2 = (f, g) => x => f(g(x))
// fairly easy to understand & explain solution using recursion &
// leaning on JavaScript's native reduce & concat methods
export const flatten = arr => !isArray(arr)
? []
: reduce(
(prev, curr) => isArray(curr)
? compose2(concat(prev), flatten)(curr)
: (!isInt(curr)
? prev // omit non-integer values
: concat(prev)(curr)
)
)([])(arr)
import test from 'ava'
import { flatten } from './flatten'
// import { flatten } from './flattenAlt'
test('nested arrays should be flattened', t => {
const flattened = flatten([[1, 2, [3]], 4])
const expected = [1, 2, 3, 4]
t.deepEqual(flattened, expected)
})
test('non-integers should be omitted', t => {
const flattened = flatten([[1, 2, 'C', [3, {}]], 4])
const expected = [1, 2, 3, 4]
t.deepEqual(flattened, expected)
})
test('flat arrays should be returned as is', t => {
const flattened = flatten([1, 2, 3, 4])
const expected = [1, 2, 3, 4]
t.deepEqual(flattened, expected)
})
test('empty arrays should be returned as is', t => {
const flattened = flatten([])
const expected = []
t.deepEqual(flattened, expected)
})
// shorthand function for the Number.isInteger method
const isInt = Number.isInteger
// shorthand function for the Array.isArray method
const isArray = Array.isArray
const buildArray = f => first => rest => [
...isArray(first)
? f(first)
: (!isInt(first)
? [] // omit non-integer values
: [first]
),
...f(rest),
]
// somewhat harder to understand & explain solution using recursion,
// pattern matching/destructuring, & the rest/spread operator
export const flatten = ([first, ...rest]) =>
first === undefined
? [] // break recursion, avoid "Max call stack size exceeded" error
: buildArray(flatten)(first)(rest)
@arecvlohe
Copy link

FP!

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