如何从球拍中的弦上去除口音?

时间:2018-08-01 12:15:42

标签: string scheme lisp racket

我有一个字符串,例如café,我需要将其转换为 cafe 。 我尝试过(string-normalize-nfd "café"),但它返回 cafe 带有重音的引号,而`((string-normalize-nfd alguém))返回 alguem m 为重音。 如何将重音字符串转换为非重音字符串?

3 个答案:

答案 0 :(得分:4)

我想不出一个可以满足您需要的内置过程,但是编写自己的实现很容易:

; 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"

答案 1 :(得分:3)

您的问题不是关于球拍的真正问题。这是关于Unicode规范化的。您要引用的函数执行以下内容中描述的“规范化规范” this page

在我看来,如果您知道原始字符串不包含重音字符,那么执行所需操作的最佳方法可能是执行规范化,然后去除所有重音字符。

答案 2 :(得分:3)

您有使用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"