如何在Kotlin中排序包含数字和特殊字符的字符串列表

rm5edbpk  于 2023-03-03  发布在  Kotlin
关注(0)|答案(2)|浏览(199)

我正在尝试按以下顺序对字符串列表进行排序:
("7foo", "FOO1", "FOO2", "foo4", "foo4_1", "foo5", "foo5_1", "FOO8", "Foo27_QA", "Foo29_QA")
我尝试使用list.sortedWith{}

val list = mutableListOf("FOO1", "FOO2", "7foo", "FOO8", "foo5","foo27_QA", "foo4_1", "foo29_QA", "foo5_1", "foo4")

val sorted2 = list.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER, { it }))

但结果是[7foo, FOO1, FOO2, Foo27_QA, Foo29_QA, foo4, foo4_1, foo5, foo5_1, FOO8]

5t7ly7z5

5t7ly7z51#

问题是你想得到的订单。
默认比较器和CASE_INSENSITIVE_ORDER比较器都遵循字典顺序。但是,您期望的结果并不是这样的顺序。
按字典顺序(不区分大小写):Foo29_QAfoo4之前,因此使用默认比较器时结果良好。
因此,您需要编写自己的比较器来应用自己的逻辑。

val sorted3 = list.sortedWith { o1, o2 -> 
    // put your comparing logic here
}

好吧,那么如何排序你的列表(这不是一个容易的任务)。我假设你的订单遵循以下模式:
{$number_prefix}{"foo"}{$number}{"_"}{$alphanumeric_suffix}
我们将按以下方式进行排序:

  • $number_prefix描述
  • $number ASC
  • $alphanumeric_suffix描述

最后,我们可以使用以下形式:

// create helper class for comparing
data class Element(
    val originalValue: String,
    val numberPrefix: Int?,
    val number: Int?,
    val suffix: String
)

// parse string into Element (for strings that not follow pattern
// `{$number_prefix}{"foo"}{$number}{"_"}{$alphanumeric_suffix}`
// this may throw an exception
fun parse(s: String): Element {
    val normalized = s.lowercase()
    val fooSplit = normalized.split("foo")

    // determine numberPrefix
    val numberPrefix = fooSplit.first().toIntOrNull()

    // parse the rest
    val suffixRest = fooSplit.last()
    val suffixRestSplit = suffixRest.split("_")

    // and get rest of the data
    val number = suffixRestSplit.first().toIntOrNull()
    val suffix = suffixRestSplit.last()

    return Element(s, numberPrefix, number, suffix)
}

fun test() {
    // define list
    val list = mutableListOf("FOO1", "FOO2", "7foo", "FOO8", "foo5", "foo27_QA", "foo4_1", "foo29_QA", "foo5_1", "foo4")

    // create a comparator with defined comparing rules
    val elementComparator = compareByDescending <Element> { it.numberPrefix }
        .thenBy { it.number }
        .thenByDescending { it.suffix }

    // and sort it with the defined comparator (map it in the fly)
    val sorted = list
        .map { parse(it) } // parse to helper-Element class
        .sortedWith(elementComparator) // compare with our defined rules
        .map { it.originalValue } // go back to original values

    // prints: [7foo, FOO1, FOO2, foo4, foo4_1, foo5, foo5_1, FOO8, foo27_QA, foo29_QA]
    println(sorted)
}
0qx6xfy6

0qx6xfy62#

您可以尝试使用此函数提取编号

fun getNumber(s: String) = ("foo(\\d+)".toRegex().find(s.lowercase())?.groups?.get(1)?.value ?: "0").toInt()

你就可以

val sorted2  = list.sortedWith(compareBy({
    getNumber(it)
}, { it }))

相关问题