我收到了一份字符串列表,需要判断它们是否按字母顺序排序。
我知道需要使用for循环并检查每个字符串的第一个字符,但我不知道如何从那里继续。
for (item in array)
println(item[0])
例如
["adam", "ben", "chloe"]
应返回 true
。同样地,对于
["ben", "adam", "chloe"]
应返回 false
。更新:自Kotlin 1.2起,以下内容可用:
最高效的变体,创建了最少的中间对象:
listOf(1, 2, 3).asSequence().zipWithNext { a, b -> a <= b }.all { it }
效率说明:仅创建两个 Sequence
对象和一个函数对象。使用 Boolean
常量作为中间值。最后的 all
调用被内联为序列上的 while
循环。
稍微不太有效率的变体:
listOf(1, 2, 3).asSequence().windowed(2).all { (a, b) -> a <= b }
它的效率略低,因为它会为原始列表的每个元素创建一个中间List(a, b)
。
@Billbucket和@AshishChaudhary在下面的答案中列出了这两种变体。
旧版本Kotlin的答案:
以下是一行代码:
val a = listOf("a", "b", "c")
a.zip(a.drop(1)).all { (a, b) -> a <= b }
// true
解释:
a.zip(a.drop(1))
返回相邻元素对。如果每对中第一个元素小于或等于下一个元素,则数组有序。
如果您想提高性能,可以首先将您的数组包装在懒序列中。在这种情况下,数组不会被复制:
a.asSequence().let { it.zip(it.drop(1)).all { (a, b) -> a < b } }
整件事是O(N)
(单遍通过数组),这对于此任务是最优的。您可以使用一个简单的一行代码:
array.zipWithNext { s1, s2 -> s1 <= s2 }.all { it }
array.zipWithNext().all { it.first <= it.second }
可以翻译为:将数组中相邻的元素组合成对,然后判断所有这些对中,每个元素对的第一个元素是否小于等于第二个元素。 - arekolekfun isAlphabetical(stringsArray: Array<String>): Boolean {
if (stringsArray.size < 2) return true
return (1 until stringsArray.size).none { stringsArray[it] <= stringsArray[it - 1] }
}
fun main(args: Array<String>) {
val testCases = arrayOf(arrayOf("adam", "ben", "chloe"), arrayOf("ben", "adam", "chloe"))
for(testCase : Array<String> in testCases){
println("The strings are: ${testCase.joinToString()}")
if (isAlphabetical(testCase)) {
println("Strings are in alphabetical order.\n")
} else {
println("Strings are not in alphabetical order.\n")
}
}
}
输出:
The strings are: adam, ben, chloe
Strings are in alphabetical order.
The strings are: ben, adam, chloe
Strings are not in alphabetical order.
<=
)。O(n log n)
并将数组转换两次为列表),但它非常易读。val test = array.asList() == array.asList().sorted()
您问题的完整代码可能如下:
println(if (array.asList() == array.asList().sorted()) "Strings are in alphabetical order." else "Strings are not in alphabetical order.")
val list = listOf("a", "b", "c")
list.windowed(2).none { (a, b) -> a > b }
// true
windowed
是一个不错的选择。但请注意,它仅在 Kotlin 1.2 及以上版本中可用。 - Aivean如果您想比较任意的Comparable
列表:
fun <T : Comparable<T>> isCollectionSortedAsc(list: Collection<T>): Boolean {
return list.zipWithNext { a, b -> a.compareTo(b) == -1 }.all { it }
}
asSequence()
,所以 zipWithNext()
会遍历整个集合并返回一个列表。 - headsvk又一个解决方案 :)
data class Result(val isInOrder: Boolean, val lastString: String) {
val toString = when {
isInOrder -> "Strings are in alphabetical order."
else -> "Strings are not in alphabetical order."
}
}
fun Array<String>.isInAlphabeticalOrder() =
this.fold(Result(true, ""), { acc, word -> Result(acc.isInOrder && acc.lastString < word, word) })
fun main(args: Array<String>) {
val test1 = arrayOf("adam", "ben", "chloe")
val test2 = arrayOf("ben", "adam", "chloe")
println(test1.isInAlphabeticalOrder().toString)
println(test2.isInAlphabeticalOrder().toString)
}
Boolean
对象,请注意,自动装箱将重用Boolean.TRUE
和Boolean.FALSE
常量(已经足够高效),并且它们可能会被JIT优化掉。 - Aivean