Как убрать акценты с веревки в Racket?

У меня есть строка типа кафе, и мне нужно перевести ее в кафе. Я пробовал (string-normalize-nfd "café"), но он возвращает кафе кавычки с акцентом, а `(string-normalize-nfd alguém) возвращает alguem с акцентом на м. Как я могу перевести строку с ударением в строку без ударения?

Вы можете использовать iconv

amirouche 14.06.2019 02:14
В чем разница между методом "==" и equals()
В чем разница между методом "==" и equals()
Это один из наиболее часто задаваемых вопросов новичкам на собеседовании. Давайте обсудим его на примере.
Замена символа по определенному индексу в JavaScript
Замена символа по определенному индексу в JavaScript
В JavaScript существует несколько способов заменить символ в строке по определенному индексу.
2
1
264
3

Ответы 3

Я не могу придумать встроенную процедуру, которая делает то, что вам нужно, но легко написать свою собственную реализацию:

; maps accented chars to unaccented chars
(define translate
  '#hash((#\á . #\a)
         (#\é . #\e)
         (#\í . #\i)
         (#\ó . #\o)
         (#\ú . #\u)))

(define (remove-accents str)
  (apply string ; convert char list back into string
         ; for each char: replace it with non-accented
         ; version, if not present leave it unmodified
         (map (λ (c) (hash-ref translate c (const c)))
              (string->list str)))) ; convert string to char list

Не забудьте добавить дополнительные сопоставления по мере необходимости, например, для включения символов в верхнем регистре и т. д. Это работает, как ожидалось:

(remove-accents "café")
=> "cafe"

На самом деле ваш вопрос не о Racket; это о нормализации Unicode. Функция, о которой вы говорите, выполняет «каноническую нормализацию», описанную на эта страница.

Мне кажется, что лучший способ сделать то, что вы хотите, - это выполнить нормализацию, а затем удалить любые символы с диакритическими знаками, если вы знаете, что исходная строка не содержит символов с диакритическими знаками.

Функции Racket string-normalize-{nfc nfd nfkc nfkd} делают то, что описано на этой странице.

Greg Hendershott 04.08.2018 19:57

У вас есть правильная идея использовать string-normalize-nfd - и он действительно работает! Просто строки Racket имеют кодировку UTF-8 и печатаются как составные или разложенные одинаково.

(string-normalize-nfd "café") ;Racket prints UTF-8 string as "café"

Вы можете увидеть, что это сработало, если преобразовать строку в байты:

(string->bytes/utf-8 (string-normalize-nfd "café")) ;#"cafe\314\201"

Учитывая это, вот черновой вариант функции. Я был бы удивлен, если бы это были абсолютно правильными для всех случаев. Но, надеюсь, этого достаточно, чтобы получить вы на своем пути, и вы можете его усовершенствовать.

(define (ascii-ize s)
  (list->string
   (for/list ([b (in-bytes (string->bytes/utf-8
                            (string-normalize-nfd s)))]
              #:when (< b 128))
     (integer->char b))))

(ascii-ize "café")   ;"cafe"
(ascii-ize "alguém") ;"alguem"

Другие вопросы по теме