Versão um pouco mais curta da mesma coisa usando recursos do ES2017, como funções de seta e desestruturação:
Função
var stableSort = (arr, compare) => arr
.map((item, index) => ({item, index}))
.sort((a, b) => compare(a.item, b.item) || a.index - b.index)
.map(({item}) => item)
Ele aceita matriz de entrada e função de comparação:
stableSort([5,6,3,2,1], (a, b) => a - b)
Ele também retorna uma nova matriz em vez de fazer uma classificação local, como a função Array.sort () embutida.
Teste
Se pegarmos a seguinte input
matriz, inicialmente classificada por weight
:
// sorted by weight
var input = [
{ height: 100, weight: 80 },
{ height: 90, weight: 90 },
{ height: 70, weight: 95 },
{ height: 100, weight: 100 },
{ height: 80, weight: 110 },
{ height: 110, weight: 115 },
{ height: 100, weight: 120 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 100, weight: 135 },
{ height: 75, weight: 140 },
{ height: 70, weight: 140 }
]
Em seguida, classifique-o height
usando stableSort
:
stableSort(input, (a, b) => a.height - b.height)
Resulta em:
// Items with the same height are still sorted by weight
// which means they preserved their relative order.
var stable = [
{ height: 70, weight: 95 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 70, weight: 140 },
{ height: 75, weight: 140 },
{ height: 80, weight: 110 },
{ height: 90, weight: 90 },
{ height: 100, weight: 80 },
{ height: 100, weight: 100 },
{ height: 100, weight: 120 },
{ height: 100, weight: 135 },
{ height: 110, weight: 115 }
]
No entanto, classificar a mesma input
matriz usando o integrado Array.sort()
(no Chrome / NodeJS):
input.sort((a, b) => a.height - b.height)
Retorna:
var unstable = [
{ height: 70, weight: 140 },
{ height: 70, weight: 95 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 75, weight: 140 },
{ height: 80, weight: 110 },
{ height: 90, weight: 90 },
{ height: 100, weight: 100 },
{ height: 100, weight: 80 },
{ height: 100, weight: 135 },
{ height: 100, weight: 120 },
{ height: 110, weight: 115 }
]
Recursos
Atualizar
Array.prototype.sort
agora está estável no V8 v7.0 / Chrome 70!
Anteriormente, o V8 usava um QuickSort instável para arrays com mais de 10 elementos. Agora, usamos o algoritmo TimSort estável.
fonte