Pular para o conteúdo

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ípioPosição em sort() cruPosição em ordenar()
Xinguara (PA)5 / 4342 / 43
Xique-Xique (BA)6 / 4343 / 43
Zabelê (PB)7 / 4344 / 43
Zacarias (SP)8 / 4345 / 43
Zortéa (SC)9 / 4347 / 43
Zé Doca (MA)10 / 4346 / 43
Água Azul do Norte (PA)11 / 431 / 43
Óbidos (PA)46 / 4340 / 43
Água Doce do Maranhão (MA)20 / 4310 / 43
Água Branca (PI)14 / 434 / 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 de ordenacao.ts (200 mil linhas, 553 ms com numeric contra 39 ms do sort() 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.