Skip to content

Instantly share code, notes, and snippets.

@stavalfi
Last active September 5, 2018 14:29
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 stavalfi/e4879379e8cb3ed609bd3054c951654d to your computer and use it in GitHub Desktop.
Save stavalfi/e4879379e8cb3ed609bd3054c951654d to your computer and use it in GitHub Desktop.
Functional Programming Practice

Functional Programming Practice

All the methods and the documentation are taken from lodash docs


Goal

Manipulating collections using functional and declerative code.

Rules
  1. No for-loops
  2. No while/do-while-loops
  3. No mutations
  4. Each lambda must be pure function by the Wikipedia definition
  5. Use only your standard library without any external libraries.
  6. You can use recursion even if there is only one function that needs that function.
  7. The result array must preserve the internal elements order of the input array.
  8. Do not break your pipeline.
  9. Do not copy-paste any code from Google. You are expected to understand which line of your code fully.
  10. Do not create any variable (primitive/object/function/class) inside your functions (function parameters are allowed).
Java notes
  1. In case you worry about performance, use collect instead of reduce in case it solved your problem.
  2. Accept array or list - it doesn't matter. (It is recommended to work with lists)
  3. Return array or list - it doesn't matter. (You can and sometimes should return Stream)
  4. Do not use inner classes, anonymous classes or any other trick to avoid lambdas.
  5. Bonus: all your implementations must support parallel execution of streams.
Javascript notes
  1. Only arrow functions and function pointers are allowed.
How to start
  1. If you are using Java and its the first time you write declarative code or you don't understand the rules, I recommend you to read: Functional Programming in Java 8 - Basic Concepts and Lambdas.
  2. If its the first time you manipulate collections, take the time to read about streams in your language.
  3. Don't skip over; the next one will be harder.
  4. If you are using Java, then I recommend you to read about the various Collectors methods.

Implement the following functions:

  1. chunk
  2. concat
  3. difference
  4. intersection
  5. findLastIndex
  6. dropRightWhile
  7. flattenDeep
  8. flattenDepth

1. chunk

  • Javascript: chunk(array, [size=1])
  • Java: <T> Stream<List<T>> chunk(List<T> list, int size)

Creates an array of elements split into groups the length of size. If array can't be split evenly, the final chunk will be the remaining elements.

Arguments
  • array (Array): The array to process.
  • [size=1] (number): The length of each chunk.
Returns

(Array): Returns the new array of chunks.

Javascript example:
chunk(['a', 'b', 'c', 'd'], 2);
// => [['a', 'b'], ['c', 'd']]
 
chunk(['a', 'b', 'c', 'd'], 3);
// => [['a', 'b', 'c'], ['d']]

2. concat

  • Javascript: concat(array, [values])
  • Java: <T> Stream<T> concat(List<T> list, T... args)

Creates a new array concatenating array with any additional arrays and/or values.

Arguments
  • array (Array): The array to concatenate.
  • [values] (...*): The values to concatenate.
Returns

(Array): Returns the new concatenated array.

Javascript example:
var array = [1];
var other = concat(array, 2, [3], [[4]]);
 
console.log(other);
// => [1, 2, [3], [[4]]]
 
console.log(array);
// => [1]

3. difference

  • Javascript: difference(array, [values])
  • Java: <T> Stream<T> difference(List<T> original, List<T>... lists)

Return an array of values not included in the other given arrays. The order and references of result values are determined by the first array.

Arguments
  • array (Array): The array to inspect.
  • [values] (...Array): The values to exclude.
Returns

(Array): Returns the new array of filtered values.

Javascript example:
difference([2, 1], [2, 3]);
// => [1]

4. intersection

Javascript: intersection([arrays]) Java: <T> Stream<T> intersection(List<T> source, List<T>... lists)

Creates an array of unique values that are included in all given arrays. The order and references of result values are determined by the first array.

Arguments

[arrays] (...Array): The arrays to inspect.

Returns

(Array): Returns the new array of intersecting values.

Javascript example:
intersection([2, 1], [2, 3]);
// => [2]

5. findLastIndex

  • Javascript: findLastIndex(array, [predicate=_.identity], [fromIndex=array.length-1])
  • Java: <T> OptionalInt findLastIndex(List<T> list, Predicate<T> predicate, int fromIndex)

Return the first index i from right to left such that both conditions fulfilled:

  1. predicate(list.at(i)) == true
  2. 0 <= i <= fromIndex.
Arguments
  • array (Array): The array to inspect.
  • [predicate=_.identity] (Function): The function invoked per iteration.
  • [fromIndex=array.length-1] (number): The index to search from.
Returns

(number): Returns the index of the found element, else -1.

Javascript example:
var users = [
  { 'user': 'barney',  'active': true },
  { 'user': 'fred',    'active': false },
  { 'user': 'pebbles', 'active': false }
];
 
findLastIndex(users, function(o) { return o.user == 'pebbles'; });
// => 2

6. dropRightWhile

  • Javascript: dropRightWhile(array, [predicate=_.identity])
  • Java: <T> Stream<T> dropRightWhile(List<T> list, Predicate<T> predicate)

Creates a slice of array excluding elements dropped from the end. Elements are dropped until predicate returns false. The predicate is invoked with three arguments: (value, index, array).

Arguments
  • array (Array): The array to query.
  • [predicate=_.identity] (Function): The function invoked per iteration.
Returns

(Array): Returns the slice of array.

Javascript example:
var users = [
  { 'user': 'barney',  'active': true },
  { 'user': 'fred',    'active': false },
  { 'user': 'pebbles', 'active': false }
];
 
dropRightWhile(users, function(o) { return !o.active; });
// => objects for ['barney']

7. flattenDeep

  • Javascript: flattenDeep(array)
  • Java: <T> Stream<T> flattenDeep(List<?> list) // each element in the list is a list of list of... list of T. Elements in the given list may and sometimes will have different type. Look at the example.

Recursively flattens array.

Arguments

array (Array): The array to flatten.

Returns

(Array): Returns the new flattened array.

Javascript example:
flattenDeep([1, [2, [3, [4]], 5]]);
// => [1, 2, 3, 4, 5]

8. flattenDepth

Note: To avoid reflection, implement this is Javascript only.

Javascript: flattenDepth(array, [depth=1])

Recursively flatten array up to depth times.

Arguments
  • array (Array): The array to flatten.
  • [depth=1] (number): The maximum recursion depth.
Returns

(Array): Returns the new flattened array.

Javascript example:
var array = [1, [2, [3, [4]], 5]];
 
flattenDepth(array, 1);
// => [1, 2, [3, [4]], 5]
 
flattenDepth(array, 2);
// => [1, 2, 3, [4], 5]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment