首先,我想写几句话来解释观察到的行为。这是正确的和预期的。字符串对象根据 ASCII 表 (http://www.asciitable.com/) 中字符的序号逐个字符进行比较。如果两个字符串具有相同的开头,则较长的字符串被认为较大。这就是为什么“文件名 10”大于“文件名 1”而“文件名 2”大于“文件名 10”的原因。
您想要实现的行为需要在比较机制中再包含一个因素:将数字考虑在内并使用算术规则进行比较。
我想你发布的例子是部分和简单的:没有数字或只有一个数字,它总是放在字符串的末尾。而一个完整的问题可能意味着一个字符串可能包含位于任何位置的任意数量的数字。
我会给你一个解决这个问题的可能方法,它解决了简单的情况(你描述的那个):
data class Item(val text: String)
data class SplitItem(val text: String, val number: Int?)
fun SplitItem.toItem() = Item(text + (number?.let { " $it" } ?: ""))
fun main() {
val items = listOf(
Item("file name with default language"),
Item("file name 1"),
Item("file name 10"),
Item("file name 11"),
Item("file name 2"),
Item("file name 20")
).shuffled()
val splitItems = items.map {
val split = it.text.split(' ')
try {
val number = Integer.parseInt(split.last())
SplitItem(
text = split.dropLast(1).joinToString(separator = " "),
number = number
)
} catch (e: NumberFormatException) {
SplitItem(
text = it.text,
number = null
)
}
}
val sortedItems = splitItems.sortedWith { o1, o2 ->
val n = compareValues(o1.number, o2.number)
val t = compareValues(o1.text, o2.text)
compareValues(n, t)
}
sortedItems
.map { it.toItem() }
.forEach { println(it) }
}
产生下一个输出:
Item(text=file name with default language)
Item(text=file name 1)
Item(text=file name 2)
Item(text=file name 10)
Item(text=file name 11)
Item(text=file name 20)
为了解决全部问题,我建议您改进这种方法。