Como alfabetizar strings com diacríticos?

7

P: como alfabeto as strings com diacríticos?

Problema

Eu tenho uma longa lista de nomes de autores, alguns dos quais têm letras com diacríticos em seus nomes (por exemplo, "á" ou "é"). Eu quero classificar esta lista em ordem alfabética.

O problema: sorting a lista com string-lesspque não classificá-los em ordem alfabética.

De acordo com a resposta aceita neste post de um site irmão , o inglês ignora os diacríticos na classificação, exceto para romper os laços. (Outros idiomas fazem isso de maneira diferente.)

Exemplo de brinquedo

Aqui está um exemplo de brinquedo. A lista de letras que eu começo já está ordenada alfabeticamente. Quando eu sortincluo esta lista string-lessp, no entanto, ela as classifica no que eu presumo que seja ordem de ponto unicode em vez de ordem alfabética:

(let ((letters '("a" "à" "á" "â" "b" "c" "e" "é" "ê")))
  (sort letters #'string-lessp))
;; => ("a" "b" "c" "e" "à" "á" "â" "é" "ê")

O que eu faço?

Como posso alfabetizar strings com sinais diacríticos?

No mínimo, gostaria de respeitar a regra "ignorar diacríticos, exceto para romper os laços" descrita acima. Idealmente, eu gostaria de poder alfabetizar de acordo com um idioma definido arbitrariamente, mas ficarei feliz em aceitar o inglês.

Dan
fonte
Boa pergunta. Gostaria de saber se depende ou não da sua configuração de idioma do sistema operacional. A alfabetização é dependente da linguagem, em geral.
Tirou

Respostas:

8

Se o código do idioma do sistema estiver definido como algo que agrupe corretamente diacríticos ( não POSIX ), isso funcionará para você:

(let ((letters '("é" "a" "à" "c" "â" "b" "á" "e" "ê")))
  (sort letters #'string-collate-lessp))
;; => ("a" "á" "à" "â" "b" "c" "e" "é" "ê")

Se isso não funcionar, você pode fornecer uma cadeia de caracteres local como o terceiro argumento string-collate-lessppara obter o que deseja. Com inglês americano em um sistema POSIX, por exemplo:

(let ((letters '("é" "a" "à" "c" "â" "b" "á" "e" "ê")))
  (sort letters (lambda (a b) (string-collate-lessp a b "en_US.UTF-8"))))

(Para inglês americano no MS-Windows, substitua "en_US.UTF-8"por "enu_USA.1252".)

Se você quiser se aprofundar um pouco mais nisso, para ver o que acontece por baixo, recomendo dar uma olhada na definição de função de str_collatein src/sysdep.c.

Sam
fonte
Exatamente o que eu estava procurando, obrigado! Como um aparte, você poderia mencionar onde é possível procurar as sequências de códigos de idioma para idiomas em inglês não americano?
Dan
@ Dan Isso é informação dependente do sistema AFAIK. Embora não seja uma lista de identificadores de localidade, essas perguntas e respostas do unix.stackexchange devem ajudá-lo a formular bons valores na maioria dos sistemas semelhantes a unix.
25419 Sam
Obrigado pelo seguimento!
Dan