Ordem alfabética em português: por que Array.sort() põe Álvaro de Carvalho depois de Zé Doca
Cole uma lista de cidades brasileiras num sort() sem locale e “Zé Doca” (Maranhão) vem por último — e logo depois dele, fora de qualquer ordem que faça sentido, começa um apêndice de 37 municípios: todos os que começam com uma letra acentuada, de Água Azul do Norte a Óleo. “Álvaro de Carvalho”, em São Paulo, está entre eles.
A fronteira, com nomes reais
Seis municípios de verdade que terminam com Z, mais os quatro primeiros da fila acentuada — misturados a mais 33 nomes reais (a amostra inteira soma 43) e ordenados pelos dois algoritmos de verdade: Array.prototype.sort() sem argumento nenhum, e ordenar(texto, "az"), a função exportada por esta ferramenta. As posições abaixo são a posição de cada nome DENTRO desses 43 — lidas de indexOf sobre o resultado real dos dois algoritmos, nunca digitadas.
| Município | Posição em sort() cru | Posição em ordenar() |
|---|---|---|
| Xinguara (PA) | 5 / 43 | 42 / 43 |
| Xique-Xique (BA) | 6 / 43 | 43 / 43 |
| Zabelê (PB) | 7 / 43 | 44 / 43 |
| Zacarias (SP) | 8 / 43 | 45 / 43 |
| Zortéa (SC) | 9 / 43 | 47 / 43 |
| Zé Doca (MA) | 10 / 43 | 46 / 43 |
| Água Azul do Norte (PA) | 11 / 43 | 1 / 43 |
| Óbidos (PA) | 46 / 43 | 40 / 43 |
| Água Doce do Maranhão (MA) | 20 / 43 | 10 / 43 |
| Água Branca (PI) | 14 / 43 | 4 / 43 |
Os seis primeiros (os que terminam com Z) ficam nas primeiras posições nos dois algoritmos — não há erro ali. É nos quatro últimos que a diferença aparece: em sort() cru eles pulam para o fim dos 43, logo depois do último Z; em ordenar(), cada um cai na sua vizinhança alfabética de verdade, longe dali. Conferido em 12 de agosto de 2026.
O que a ferramenta já mostra, em miniatura
A ferramenta desta casa já explica a causa com sete palavras: sort() compara ponto de código Unicode, não letra do alfabeto — maiúscula vem antes de minúscula, e toda vogal acentuada (código acima de 192) vem depois de qualquer letra de A a Z, maiúscula ou minúscula (até 122). O conserto publicado ali é Intl.Collator("pt-BR", { numeric: true }), que este artigo reusa — é a mesma instância, não uma cópia.
O que a página da ferramenta não tem é a MAGNITUDE. Um exemplo de sete palavras prova que o defeito existe; não diz se ele estraga uma lista de verdade um pouco ou por completo. Fomos medir.
Não é “um pouco estranho no fim” — é uma parede
No catálogo inteiro de 5.571 municípios do IBGE, 37 começam com maiúscula acentuada (Á Â Ã É Í Ó Ú). Em sort() cru, os 37 ocupam as posições 5.534 a 5.570 — as ÚLTIMAS 37 de 5.571, sem um único intruso entre eles e sem um único deles fora dali. Não é uma cauda que vai desbotando — é um bloco compacto, colado no fim, com uma parede de cada lado.
Na ordem certa, os MESMOS 37 municípios se espalham da posição 44 à 3.434 — dentro dos primeiros 61,64% da lista, cada um junto da sua vizinhança alfabética de verdade. A distância entre as duas faixas é o tamanho do erro: praticamente a lista inteira.
O pior caso: uma cidade pulando 5.493 lugares
Águas da Prata, em SP, é a que mais se desloca entre as duas ordens. Na ordem certa ela é a posição 64 — companhia natural das outras cidades que começam com “Águas”. Em sort() cru ela cai na posição 5.557, um salto de 5.493 posições — 98,6% do comprimento da lista inteira, só por causa de uma letra.
A lista inteira, não só os acentuados
Restringir a conta aos 37 que começam com letra acentuada esconde o tamanho real do problema — o resto da lista também se mexe, porque tirar 37 nomes de onde deveriam estar e empurrá-los para o fim desloca todo mundo que vinha depois. Comparando as duas ordens posição a posição, 5.560 dos 5.571 municípios (99,8%) terminam numa posição diferente entre sort() cru e a ordem certa — deslocamento médio de 91,7 posições por município.
Contando cada PAR de municípios da lista (15.515.235 pares possíveis, a combinação de 5.571 dois a dois), 281.630 saem na ordem RELATIVA errada entre uma ordem e outra — 1,82% do total. Não é o alfabeto “um pouco torto”: é uma fração mensurável e nada pequena de toda comparação possível na lista inteira do país.
Por que ninguém percebe olhando
O comentário de ordenacao.ts já registra a razão: uma lista fora de ordem no MEIO chama atenção — “Cesar” antes de “Amaral” é óbvio para qualquer leitor. Uma lista errada só no FIM passa por correta, porque ninguém confere as últimas linhas com o mesmo cuidado que confere o topo. É exatamente aí, nas últimas 37 posições de 5.571, que os 37 municípios acentuados se escondem — um erro desenhado para não ser visto.
O que este artigo não mede
- Não medimos nome de PESSOA nem sobrenome — o segundo diferencial da ferramenta (
sobrenome.ts, a regra ABNT de entrar pelo sobrenome) não tem, dentro deste site, um corpus real e grande de nomes completos para medir do mesmo jeito que medimos município. A lista do IBGE é de cidade, não de gente. - Não medimos o modo numérico (
numeric: true) contra o catálogo do IBGE, porque nome de município não carrega número — esse diferencial já está medido, com timing incluído, no próprio comentário deordenacao.ts(200 mil linhas, 553 ms comnumericcontra 39 ms dosort()cru). - O catálogo tem data: baixado de servicodados.ibge.gov.br/api/v1/localidades/municipios em 12 de agosto de 2026. O IBGE cria e funde município raramente, mas os números grandes desta página são desse dia, não recalculados a cada visita.
- Não testamos outro motor JavaScript além do V8 (Node, que é o que roda este build). A ordem de
sort()sem comparador depende só da comparação de pontos de código — que o padrão ECMA-262 define igual em qualquer motor —, então o resultado não deveria mudar; não confirmamos isso rodando em outro motor de verdade.