Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Sorting sans Loop

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Sorting sans Loop

In the JavaScript world, Array.prototype.map is one of the most commonly used higher-order functions. Do you also know that map combined with other Array's functions can be leveraged to construct a sequence? In fact, it is entirely possible to implement a sorting algorithm or to perform a search operation with just the higher-order functions of the built-in Array object, without using explicit for/while statements. Learn more about it from this talk!

Avatar for Ariya Hidayat

Ariya Hidayat

June 08, 2016
Tweet

More Decks by Ariya Hidayat

Other Decks in Programming

Transcript

  1. • Just because you can do it, doesn’t mean you

    should do it • Be advised of any performance implication • Don’t optimize prematurely, judge wisely between readability and speed
  2. map calls callbackfn once for each element in the array,

    in ascending order, and constructs a new Array from the results. callbackfn is called with three arguments: • the value of the element • the index of the element, and • the object being traversed. [ ... ].map(callbackfn)
  3. [1, 2, 3].map(function (x) { return x * x; });

    [1, 4, 9] [7, 7, 7].map(function (x, y) { return y; }); [0, 1, 2] y = index x = element
  4. [ ... ].reduce(callbackfn, initial) callbackfn is called with four arguments:

    • the previousValue (or value from the previous call to callbackfn), • the currentValue (value of the current element) • the currentIndex, and • the object being traversed.
  5. [1, 2, 3, 4, 5].reduce(function (sum, i) { return sum

    + i; }); [1, 2, 3, 4, 5].reduce(function (sum, i) { return sum + i; }, 100); 15 115 [1, 2, 3].reduce(function(result, x) { return result.concat(x + 2); }, []); [3, 4, 5]
  6. var result = []; for (var i = 1; i

    < 4; ++i) result.push(i) console.log(result); // [1, 2, 3]
  7. var list = ''; for (var i = 0; i

    < 26; ++i) list += String.fromCharCode(i + 65); console.log(list); // 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  8. Section 11.8.7 0 in Array(3); // false 1 in Array(3);

    // false 2 in Array(3); // false 2 in [,,9]; // true toString relies on join (Section 15.4.4.5) join convertes undefined or null to an empty string
  9. Array.apply(0, Array(3)).map(function (x, y) { return y + 1; });

    [1, 2, 3] Array.apply(0, Array(3)).map(function (x, y) { return (y + 1) * (y + 1); }); [1, 4, 9] Array.apply(0, Array(3)) [undefined, undefined, undefined]
  10. function factorial(n) { var result = 1; for (var i

    = 1; i <= n; ++i) result *= i; return result; } factorial(5) 120 1 * 2 * 3 * 4 * 5
  11. x z 1 1 0 2 1 6 2 24

    3 120 4 x + x * z
  12. function findLongest(array) { for (var i = 0, longest =

    ''; i < array.length; ++i) if (array[i].length > longest.length) longest = array[i]; return longest; } findLongest(['ab', 'abc', 'a']) 'abc'
  13. function findLongest(array) { return array.reduce(function (longest, entry) { return entry.length

    > longest.length ? entry : longest; }, '' }); } findLongest(['ab', 'abc', 'a']) 'abc'
  14. function findLongest(array) { return array.reduce(function (longest, entry, index) { return

    entry.length > longest.value.length ? { index: index, value: entry } : longest; }, { index: -1, value: '' }); } findLongest(['ab', 'abc', 'a']) { index: 1, value: 'abc' }
  15. function findSmallest(array) { return array.reduce(function (min, entry, index) { return

    min.value < entry ? { index: index, value: entry } : min; }, { value: null }); } findSmallest([14, 3, 19, 77]) { index: 1, value: 3 }
  16. function sort(input) { var array = input.slice(0); return Array.apply(0, Array(array.length)).map(function

    () { return array.splice(findSmallest(array).index, 1).pop(); }); } Before splice After splice [14, 3, 19, 77] [14, 19, 77] { index: 1, value: 3 }
  17. function sort(input) { var array = input.slice(0); return Array.apply(0, Array(array.length)).map(function

    () { return array.splice(array.reduce(function (min, entry, index) { return min.value < entry ? min : index: index, value: entry }; }).index, 1).pop(); }); }
  18. function compareswap(array, p, q) { if (array[p] < array[q]) {

    var temp = array[q]; array[q] = array[p]; array[p] = temp; } } compareswap(entries, 0, 1); compareswap(entries, 1, 2); compareswap(entries, 2, 3); compareswap(entries, 0, 1); compareswap(entries, 1, 2); compareswap(entries, 0, 1); “Comparator” Sorting sequences
  19. function compareswap(array, p, q) { if (array[p] < array[q]) {

    var temp = array[q]; array[q] = array[p]; array[p] = temp; } } compareswap(entries, 0, 1); compareswap(entries, 1, 2); compareswap(entries, 0, 1); “Comparator” Sorting sequences
  20. function sort(network, entries) { for (var i = 0; i

    < network.length; ++i) compareswap(entries, network[i], network[i] + 1) }
  21. function createNetwork(N) { return Array.apply(0, Array(N)).reduce(function (network, _, y) {

    return network.concat(Array.apply(0, Array(N - y - 1)) .map(function(_, x) { return x; })); }, []); } [0, 1, 2, 0, 1, 0]