Claudia Hernández
October 28, 2017
710

How to sort your socks using Javascript

No matter your experience in JS, you have probably came across the Array#sort method at some point. Do you remember the first time you tried sorting numbers? You were probably astonished that the sort method does not sort things out quite as we might expect.

Believe it or not, there is actually much more going on than meets the eye! Let’s get our computer science hat on and explore some useful sorting algorithms currently implemented by JS engines used by Node such as Chrome's V8 and Microsoft's Chakra. As a developer, learning how these algorithms work, why and when to use them will help you create more performant and consistent applications!

October 28, 2017

Transcript

\$ -

3. @koste4 Algoritmo que acomoda elementos de una lista en cierto

orden. Los ordenes más usados son numérico y lexicográfico ALGORITMO  DE ORDENAMIENTO
4. @koste4 ARRAY SORT EN JS # 1 myArray = [33,

2, 98, 25, 4] 2 myArray.sort() // [ 2, 25, 33, 4, 98 ]
5. @koste4 ORDENAMIENTO LEXICOGRÁFICO Si no se provee , los elementos

son ordenados convirtiéndolos a strings y comparando la posición del valor Unicode de dichos strings compareFunction D
6. @koste4 VALOR UNICODE 1 colors = ['red', 'blue'] 2 colors.sort()

3 // ['blue', 'red'] 4 5 numbers = [80, 9] 6 numbers.sort() 7 // [80, 9] 80 9 = = 56 48 57 00
7. @koste4 1 colors = ['red', 'blue'] 2 colors.sort() 3 //

['blue', 'red'] 4 5 numbers = ['80', '9'] 6 numbers.sort() 7 // [80, 9] VALOR UNICODE 80 9 = = 56 48 57 00
8. @koste4 ARRAY SORT EN JS # 1 // [ 2,

25, 33, 4, 98 ]
9. @koste4 ARRAY SORT EN JS # 1 myArray = [33,

2, 98, 25, 4] 2 myArray.sort( (a,b) => a - b ) 3 // [ 2, 4, 25, 33, 98 ]
10. @koste4 ¿ALGUNA VEZ TE HAS CUÁL ES PREGUNTADO EL ALGORITMO

USADO EN LA FUNCIÓN SORT NATIVA DE ? JAVASCRIPT
11. https://hg.mozilla.org/mozilla-central/ﬁle/28be8df0deb7/js/src/jsarray.cpp M E R G E S O R T

S O R T S P I D E R   M O N K E Y
12. https://hg.mozilla.org/mozilla-central/ﬁle/28be8df0deb7/js/src/jsarray.cpp M E R G E S O R T

S O R T S P I D E R   M O N K E Y
13. https://hg.mozilla.org/mozilla-central/ﬁle/28be8df0deb7/js/src/jsarray.cpp M E R G E S O R T

S O R T S P I D E R   M O N K E Y

S O R T V 8

S O R T V 8

T N I T R O
17. https://github.com/Microsoft/ChakraCore/blob/master/ lib/Common/DataStructures/QuickSort.h Q U I C K S O R

T S O R T C H A K R A
18. @koste4 Motor JS Algoritmo de Ordenamiento SpiderMonkey F I R

E F O X Insertion Sort (arreglos pequeños)  Merge Sort V8 C H R O M E Insertion Sort (arreglos pequeños)  Quick Sort Nitro S A F A R I Merge Sort Chakra I N T E R N E T E X P L O R E R QuickSort

20. @koste4 ESTABILIDAD Un algoritmo de ordenamiento estable es aquel en

el cual elementos iguales conservan sus posiciones iniciales después del ordenamiento

22. @koste4 INSERTION SORT El arreglo es recorrido de manera secuencial

y los elementos no ordenados son movidos e insertados en una sub-lista ordenada que se encuentra en el mismo arreglo
23. @koste4 1 function InsertionSort(arr) { 2 3 let len =

arr.length, // número de elementos en el arreglo 4 value, // valor a comparar 5 i, // index de la sección sin ordenar 6 j; // index de la sección ordenada 7 8 for(i = 1; i < len; i++) { 9 10 // guarda el valor actual porque puede cambiar después 11 value = arr[i] 12 13 // Cuando el valor de la sección ordenada es mayor que el valor en la 14 // sección no ordenada, mover todos los elementos en la sección uno 15 // por uno. Esto crea un espacio en el cual insertar el valor. 16 for (j = i - 1; j >= 0 && arr[j] > value; j--) { 17 arr[j+1] = arr[j] 18 } 19 arr[j+1] = value 20 } 21 22 return arr 23 24 }

25. @koste4 DIVIDE Y VENCERÁS Tácticas de Napoleón Bonaparte "Genio Militar"

Dividir al enemigo en dos y sorprender por un costado 1 3 2 Vencer (atacar) al enemigo pues éste será reducido a la mitad de su tamaño original Concentrar artillería y recursos en un sólo flanco
26. @koste4 MERGE SORT Divide el arreglo en 2 sub- arreglos

con n/2 elementos cada uno 1 3 2 Vence (ordena) cada sub- arreglo. Al menos que el arreglo sea suficientemente pequeño, usa recursión Combina las soluciones de los sub-arreglos fusionándolos en un sólo arreglo
27. 1 function MergeSort(arr) { 2 3 let len = arr.length,

// número de elementos en el arreglo 4 middle, // mitad del arreglo 5 left, // lado izquierdo del arreglo 6 right // lado derecho del arreglo 7 8 // Arreglos de tamaño 0 y 1 no necesitan ser ordenados 9 if (len < 2) { 10 return arr 11 } 12 13 middle = Math.floor(len/2) 14 15 left = arr.slice(0, middle) // lado izquierdo, de 0 a la mitad 16 right = arr.slice(middle) // lado derecho, de la mitad al final 17 18 return merge(MergeSort(left), MergeSort(right)) 19 20 }
28. 1 // Fusiona 2 arreglos ya ordenados 2 function merge(left,

right) { 3 let result = [], 4 i = 0, 5 j = 0 6 7 while(i < left.length && j < right.length) { 8 9 // Elementos en ambos arreglos son comparados uno contra el otro. 10 // El elemento más pequeño es insertado en los resultados. 11 12 // Cada ves que un valor de un arreglo es agregado, su 13 // índice correspondiente es incrementado. 14 15 if(left[i] < right[j]) { 16 result.push(left[i++]) 17 } else { 18 result.push(right[j++]) 19 } 20 } 21 22 // Una vez que uno de los arreglos haya terminado, los elementos 23 // restantes del otro arreglo son agregados a los resultados. 24 25 return result.concat(left.slice(i)).concat(right.slice(j)) 26 27 }

30. @koste4 QUICK SORT Encuentra un pivote 1 3 2 Divide

el arreglo de manera que todos los elementos menores al pivote estén a la izquierda y los mayores a la derecha del pivote Vence (ordena) los arreglos
31. 1 // Encuentra un “pivote” en el arreglo para comparar

2 // todos sus elementos y moverlos antes o después de 3 // dicho pivote dependiendo de sus valores 4 function QuickSort(arr, left = 0, right = arr.length - 1) { 5 let len = arr.length, 6 index 7 8 if(len > 1) { 9 10 index = partition(arr, left, right) 11 12 if(left < index - 1) { 13 QuickSort(arr, left, index - 1) 14 } 15 16 if(index < right) { 17 QuickSort(arr, index, right) 18 } 19 20 } 21 22 return arr 23 24 }
32. 1 function partition(arr, left, right) { 2 let middle =

Math.floor((right + left) / 2), 3 pivot = arr[middle], 4 i = left, // Inicializa el apuntador en el primer elemento del arreglo 5 j = right // Inicializa el apuntador en el último elemento del arreglo 6 7 while(i <= j) { 8 // Mueve el apuntador izquierdo a la derecha hasta que el valor 9 // a la isquierda sea más grande que el pivote 10 while(arr[i] < pivot) { 11 i++ 12 } 13 14 // Mueve el apuntador derecho a la izquierda hasta que el valor 15 // a la derecha sea menor que el pivote 16 while(arr[j] > pivot) { 17 j-- 18 } 19 20 // Si el apuntador izquierdo es menor o igual al apuntador derecho, 21 // intercambia valores 22 if(i <= j) { 23 [arr[i], arr[j]] = [arr[j], arr[i]] // ES6 destructuring swap 24 i++ 25 j-- 26 } 27 } 28 29 return i 30 31 }

34. 1 Array.prototype.InsertSort = function() { 2 /* tu implementación aquí

*/ 3 } 4 5 Array.prototype.MergeSort = function() { 6 /* tu implementación aquí */ 7 } 8 9 Array.prototype.QuickSort = function() { 10 /* tu implementación aquí */ 11 } 12 13 myArray.InsertSort() 14 myArray.MergeSort() 15 myArray.QuickSort()

41. const people = [ { name: 'Yamil Asusta', age: 26

}, { name: 'Mathias Bynens', age: 54 }, { name: 'Arunesh Chandra', age: 17 }, { name: 'Julián Duque', age: 12 }, { name: 'Michele Garrett', age: 32 }, { name: 'Daniel Gimenez', age: 26 }, { name: 'Claudia Hernández', age: 26 }, { name: 'Jeff Lembeck', age: 11 }, { name: 'Kat Marchán', age: 6 }, { name: 'Karisa McKelvey', age: 26 }, { name: 'Kassandra Perch', age: 26 }, { name: 'Nikhila Ravi', age: 26 }, { name: 'Athan Reines', age: 42 }, { name: 'Bert Spaan', age: 11 }, { name: 'Mariano Vazquez', age: 32 }, ]

44. [{ name: 'Kat Marchán', age: 6 }, { name: 'Jeff

Lembeck', age: 11 }, { name: 'Bert Spaan', age: 11 }, { name: 'Julián Duque', age: 12 }, { name: 'Arunesh Chandra', age: 17 }, { name: 'Daniel Gimenez', age: 26 }, { name: 'Claudia Hernández', age: 26 }, { name: 'Nikhila Ravi', age: 26 }, { name: 'Yamil Asusta', age: 26 }, { name: 'Karisa McKelvey', age: 26 }, { name: 'Kassandra Perch', age: 26 }, { name: 'Michele Garrett', age: 32 }, { name: 'Mariano Vazquez', age: 32 }, { name: 'Athan Reines', age: 42 }, { name: 'Mathias Bynens', age: 54 }]

46. [{ name: 'Kat Marchán', age: 6 }, { name: 'Jeff

Lembeck', age: 11 }, { name: 'Bert Spaan', age: 11 }, { name: 'Julián Duque', age: 12 }, { name: 'Arunesh Chandra', age: 17 }, { name: 'Yamil Asusta', age: 26 }, { name: 'Daniel Gimenez', age: 26 }, { name: 'Claudia Hernández', age: 26 }, { name: 'Karisa McKelvey', age: 26 }, { name: 'Nikhila Ravi', age: 26 }, { name: 'Kassandra Perch', age: 26 }, { name: 'Michele Garrett', age: 32 }, { name: 'Mariano Vazquez', age: 32 }, { name: 'Athan Reines', age: 42 }, { name: 'Mathias Bynens', age: 54 }]

lenguaje
50. @koste4 PERO… ¿NO ES LENTO? Los arreglos en JS tienen

metódos cómo  , , y por supuesto    forEach map reduce sort Todos éstos métodos reciben una   función callback como argumento

52. @koste4 PERO… ¿NO ES LENTO? El cambio de contexto cuesta

caro Mantenerse en el mismo contexto de  ejecución y en el mismo lenguaje   permite mejor rendimiento
53. @koste4 Motor JS Algoritmo de Ordenamiento Self-Host ? SpiderMonkey F

I R E F O X Insertion Sort (arreglos pequeños)  Merge Sort No V8 C H R O M E Insertion Sort (arreglos pequeños)  Quick Sort Sí Nitro S A F A R I Merge Sort Sí Chakra I N T E R N E T E X P L O R E R QuickSort No

62. @koste4 MÁS SOBRE EL TEMA… The Algorithm Design Manual by

Steven S. Skiena Foundations of Algorithms by Richard Neapolitan & Kumarss Naimipour