Frequentemente me deparo com a necessidade de ordenar uma lista usando Array.prototype.sort() dependendo de diversos critérios.

Ai lá vinha todas aquelas questões de quando usar -1, 0 e 1 para obter uma ordenação ascendente ou descendente, qual elemento colocar primeiro, qual a forma mais curta de fazer sem ter que usar todos aqueles IF’s aninhados, …

Imagine que você precisa comprar um produto X na quantidade Y e você tem a lista de lojas que possuem esse produto, quantidade, preço e tempo de entrega de cada loja.

Dito isso, a prioridade de ordenação ficou definida como: preço (ascendente), quantidade (descendente) e tempo de entrega (ascendente)

Até ontem eu teria feito da seguinte forma:

1
2
3
4
5
6
7
8
9
10
11
12
stores.sort(function (a, b) {
  if (a.price == b.price) {
    if (a.stock == b.stock) {
      if (a.time == b.time) {
        return 0;
      }
      return (a.time < b.time?-1:1); // tempo de entrega ASC
    }
    return (a.stock > b.stock?-1:1); // quantidade DESC
  }
  return (a.price < b.price?-1:1); // preço ASC
});

Para facilitar, eu já tinha definido alguns padrões mentais, como por exemplo:

  • atribuir sempre os nomes a e b aos parâmetros
  • comparar sempre a com b e não o contrário
  • -1 sempre na condição TRUE do ternário e 1 no FALSE

Percebam que esses padrões estão sempre na ordem ascendente… a depois b, -1 depois 1. Isso facilitou muito minha compreensão e agora ficou meio automático, nem penso mais nisso, simplesmente faço.

O que variava basicamente era o símbolo de MENOR e MAIOR e para decorar qual usar em qual situação pensei o seguinte: a parte superior do símbolo de MENOR é uma reta ASCENDENTE. Da mesma forma, a parte superior do símbolo de MAIOR é uma reta DESCENDENTE. Pronto, fim dos problemas!

Ainda não, ainda ficava encucado com o monte de IF’s aninhados. Como eu poderia reduzí-los?

Então li sobre Sorting with map e achei algo mágico:

1
2
3
mapped.sort(function(a, b) {
  return +(a.value > b.value) || +(a.value === b.value) - 1;
});

Fantástico! A versatilidade do JavaScript nos permite algo como isso. Uma simples condição com conversões implícitas (casting) e alguns cálculos matemáticos atendem a condição dos benditos -1, 0 e 1.

Para resumir a história, com alguns ajustes, utilizei essa técnica no exemplo inicial da seguinte forma:

1
2
3
4
5
stores.sort(function (a, b) {
  return -(a.price < b.price) || +(a.price != b.price) // preço ASC
      || -(a.stock > b.stock) || +(a.stock != b.stock) // quantidade DESC
      || -(a.time < b.time) || +(a.time != b.time); // tempo de entrega ASC
});

Então procurei definir os seguintes padrões mentais:

  • valor negativo e operador (MENOR ou MAIOR) na primeira condição
  • valor positivo e operador DIFERENTE na segunda condição

Novamente, ordem ascendente… negativo depois positivo. Os outros padrões permanecem os mesmos.

Enfim, acredito ter chegado ao fim da saga em busca da ordenação mais simplificada possível em JavaScript.

Share
Tags:
Categorias: Programação
Wesley Menezes

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.