【发布时间】:2019-01-09 00:19:12
【问题描述】:
我有一个类似 cafe 的字符串,我需要将它翻译成 cafe。
我试过(string-normalize-nfd "café"),但它返回 cafe 一个带重音的引号,而 `(string-normalize-nfd alguém) 返回 alguem m 的重音。
如何将重音字符串翻译成非重音字符串?
【问题讨论】:
-
你可以使用iconv
我有一个类似 cafe 的字符串,我需要将它翻译成 cafe。
我试过(string-normalize-nfd "café"),但它返回 cafe 一个带重音的引号,而 `(string-normalize-nfd alguém) 返回 alguem m 的重音。
如何将重音字符串翻译成非重音字符串?
【问题讨论】:
您有正确的想法来使用string-normalize-nfd——它确实有效!只是 Racket 字符串是 UTF-8 和 print 组成或分解的一样。
(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"
【讨论】:
您的问题并不是关于 Racket 的问题。它是关于 Unicode 规范化的。您所指的功能执行描述的“规范规范化” this page。
在我看来,如果您知道原始字符串不包含重音字符,那么执行规范化然后去除所有重音字符的最佳方法可能是执行您想要的操作。
【讨论】:
string-normalize-{nfc nfd nfkc nfkd} 函数执行该页面上描述的操作。
我想不出一个可以满足你需要的内置程序,但编写你自己的实现很容易:
; 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"
【讨论】: