如何迭代字符串,以便组合字符与其基本字符保持一致?

问题描述 投票:0回答:1

我正在尝试迭代以下字符串:

mɔ̃tr

但无论我做什么,它总是最终被处理为:

m ɔ ̃ t r

波浪号似乎与反转的 c 分离。

我的第一个尝试是执行以下操作:

"mɔ̃tr".map {
    print(it)
}

波形符不会与反转的 c 保持一致。

我看到了以下迭代器的建议:

fun codePoints(string: String): Iterable<String> {
    return object : Iterable<String> {
        override fun iterator(): MutableIterator<String> {
            return object : MutableIterator<String> {
                var nextIndex = 0
                override fun hasNext(): Boolean {
                    return nextIndex < string.length
                }

                override fun next(): String {
                    val result = string.codePointAt(nextIndex)
                    nextIndex += Character.charCount(result)
                    return String(Character.toChars(result))
                }

                override fun remove() {
                    throw UnsupportedOperationException()
                }
            }
        }
    }
}

但这给出了与前面的示例相同的输出。

我已经被这个看似简单的问题困扰一天了,我只想处理这个字符串,就好像它有 4 个字符,而不是 5 个字符一样。

有什么建议吗?

java kotlin utf-16
1个回答
11
投票

“ɔ̃”由两个 Unicode 代码点组成。这就是为什么您显示的代码点迭代器仍然将 ɔ̃ 视为单独的。

“ɔ̃”是单个字素簇。要迭代这些,您需要一个

java.text.BreakIterator
。在文档中,有一个示例向您展示了如何操作。

public static void printEachForward(BreakIterator boundary, String source) {
    int start = boundary.first();
    for (int end = boundary.next();
         end != BreakIterator.DONE;
         start = end, end = boundary.next()) {
         System.out.println(source.substring(start,end));
    }
}

在 Kotlin 中,您可以在

String
上编写扩展函数,它会返回字素簇的
Sequence

fun String.graphemeClusterSequence() = sequence {
    val iterator = BreakIterator.getCharacterInstance()
    iterator.setText(this@graphemeClusterSequence)
    var start = iterator.first()
    var end = iterator.next()
    while (end != BreakIterator.DONE) {
        yield([email protected](start, end))
        start = end
        end = iterator.next()
    }
}

现在

"mɔ̃tr".graphemeClusterSequence().forEach { println(it) }
打印:

m
ɔ̃
t
r
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.