【问题标题】:Removing accents and diacritics in kotlin删除 kotlin 中的重音符号和变音符号
【发布时间】:2018-08-07 16:34:56
【问题描述】:

有什么方法可以在 kotlin 中将 'Dziękuję' 之类的字符串转换为 'Dziekuje' 或 'šećer' 为 'secer'。我尝试过使用 java.text.Normalizer,但它似乎没有达到预期的效果。

【问题讨论】:

  • "但它似乎没有按预期的方式工作。"如何?结果是什么?
  • 对不起。我忘了将正则表达式转换为正则表达式。基本上我的意思是我缺乏使用规范化器的任何经验,因此几乎不知道我在说什么。

标签: string kotlin


【解决方案1】:

TL;DR:

  1. 使用Normalizer 规范分解Unicode 文本。
  2. 删除非空格组合字符 (\p{Mn})。

fun String.removeNonSpacingMarks() =
    Normalizer.normalize(this, Normalizer.Form.NFD)
    .replace("\\p{Mn}+".toRegex(), "")

长答案:

使用Normalizer,您可以将原始文本转换为等效的组合或分解形式。

  • NFD:规范分解。
  • NFC:规范分解,然后是规范组合。

.
(有关规范化的更多信息可以在Unicode® Standard Annex #15 中找到)

在我们的例子中,我们对 NFD 规范化形式感兴趣,因为它允许我们将所有组合字符与基本字符分开。

分解文本后,我们必须运行一个正则表达式来删除分解产生的与组合字符相对应的所有新字符。

组合字符是特殊字符,旨在相对于关联的基本字符进行定位。 Unicode 标准区分了两种类型的组合字符:间距和非间距。

我们只对非间距组合字符感兴趣。变音符号是该组的主要类别(但不是唯一的类别),用于拉丁语、希腊语和西里尔字母及其亲属。

要使用正则表达式删除非空格字符,我们必须使用\p{Mn}。该组包括all the 1,826 non-spacing characters

其他答案使用\p{InCombiningDiacriticalMarks},此块仅包括组合变音符号。它是\p{Mn}子集,仅包含112 characters

【讨论】:

    【解决方案2】:

    Normalizer 只完成了一半的工作。以下是你可以如何使用它:

    private val REGEX_UNACCENT = "\\p{InCombiningDiacriticalMarks}+".toRegex()
    
    fun CharSequence.unaccent(): String {
        val temp = Normalizer.normalize(this, Normalizer.Form.NFD)
        return REGEX_UNACCENT.replace(temp, "")
    }
    
    assert("áéíóů".unaccent() == "aeiou")
    

    它是这样工作的:

    我们正在调用 normalize()。如果我们通过 à,该方法返回 a + ` 。然后使用正则表达式,我们清理字符串以仅保留有效的 US-ASCII 字符。

    来源:http://www.rgagnon.com/javadetails/java-0456.html

    注意Normalizer 是一个Java 类;这不是纯 Kotlin,它只能在 JVM 上运行。

    【讨论】:

    • 谢谢。这正是我想要的。
    【解决方案3】:

    这是一个您可以进一步使用和扩展的扩展功能:

    fun String.normalize(): String {
        val original = arrayOf("ę", "š")
        val normalized =  arrayOf("e", "s")
    
        return this.map { it ->
            val index = original.indexOf(it.toString())
            if (index >= 0) normalized[index] else it
        }.joinToString("")
    }
    

    像这样使用它:

    val originalText = "aębšc"
    val normalizedText = originalText.normalize()
    println(normalizedText)
    

    将打印

    aebsc

    使用尽可能多的元素扩展数组originalnormalized

    【讨论】:

    • 感谢您的回答。这是整个规范化器的一个很好的解决方法。
    • 我最终使用了这个解决方案,因为 Normalizer 对 Ø 字符没有影响,我想将其转换为 O。
    【解决方案4】:

    如果有人在 kotlin 中努力做到这一点,这段代码就像一个魅力。 为了避免不一致,我还使用了 .toUpperCase 和 Trim()。然后我施放这个函数:

    fun stripAccents(s: String):String{
    
    if (s == null) {
            return "";
        }
    
        val chars: CharArray = s.toCharArray()
    
        var sb = StringBuilder(s)
        var cont: Int = 0
    
        while (chars.size > cont) {
            var c: kotlin.Char
            c = chars[cont]
            var c2:String = c.toString()
           //these are my needs, in case you need to convert other accents just Add new entries aqui
            c2 = c2.replace("Ã", "A")
            c2 = c2.replace("Õ", "O")
            c2 = c2.replace("Ç", "C")
            c2 = c2.replace("Á", "A")
            c2 = c2.replace("Ó", "O")
            c2 = c2.replace("Ê", "E")
            c2 = c2.replace("É", "E")
            c2 = c2.replace("Ú", "U")
    
            c = c2.single()
            sb.setCharAt(cont, c)
            cont++
    
        }
    
        return sb.toString()
    
    }
    

    要使用这些有趣的代码,请像这样:

    var str: String
    str = editText.text.toString() //get the text from EditText
    str = str.toUpperCase().trim()
    
    str = stripAccents(str) //call the function
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-03
      • 2010-09-19
      • 2012-12-10
      • 2015-08-30
      • 2016-06-26
      相关资源
      最近更新 更多