在 Kotlin 中使用 Int 和 String 排序 ArrayList
Order ArrayList with Int and String in Kotlin
我有给定的数组
val things = arrayOf<Any>("Jack", 8, 2, 6, "King", 5, 3, "Queen", "Jack");
下面是我用过的代码
things.set(things.indexOf("Jack"), 11);
things.set(things.indexOf("Queen"), 12);
things.set(things.indexOf("King"), 13);
things.sort();
things.set(things.indexOf(11), "Jack"));
things.set(things.indexOf(12), "Queen");
things.set(things.indexOf(13), "King");
things.joinToString(":");
things.forEach { System.out.print(it) }
这是我不断收到的错误
Unexpected tokens (use ';' to separate expressions on the same line)
Expecting an element
删除尾随括号后,出现以下错误
Exception in thread "main" java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')
at java.lang.String.compareTo (:-1)
at java.util.ComparableTimSort.binarySort (:-1)
at java.util.ComparableTimSort.sort (:-1)
问题是你有两次“杰克”。 things.set(things.indexOf("Jack"), 11);
只把第一个改成11,第二个不改
val things = arrayOf<Any>("Jack", 8, 2, 6, "King", 5, 3, "Queen", "Jack");
things.set(things.indexOf("Jack"), 11);
things.set(things.indexOf("Queen"), 12);
things.set(things.indexOf("King"), 13);
println(things.contentToString()) //prints [11, 8, 2, 6, 13, 5, 3, 12, Jack]
现在,我可能会怎么做,是这样的:
fun main() {
val things = arrayOf("Jack", 8, 2, 6, "King", 5, 3, "Queen", "Jack")
things.sortWith(compareBy { it.toInt() })
println(things.contentToString()) //prints [2, 3, 5, 6, 8, Jack, Jack, Queen, King]
}
val mapping = mapOf("Jack" to 11, "Queen" to 12, "King" to 13)
fun Any.toInt() : Int {
if (this is Int) return this
return mapping[this] ?: 0
}
您的列表中有 2 个 Jack
,因此当您使用 indexOf()
时,它 returns 是该项目第一次出现的索引。
things.set(things.indexOf("Jack"), 11);
things.set(things.indexOf("Queen"), 12);
things.set(things.indexOf("King"), 13);
这会将您的列表更改为
[11, 8, 2, 6, 13, 5, 3, 12, Jack]
现在,当您对 things
应用 sort()
操作时。它在 Jack
上抛出 ClassCastException
,因为它是 string
,而不是 int
。
要找到一个值的所有 indexes
,以便您可以替换它们,您可以创建一个 extension
函数,该函数 returns 一个值的所有索引的列表。
fun <T> Array<T>.indexesOfAll(predicate: (T) -> Boolean): List<Int> {
return mapIndexedNotNull { index, any ->
index.takeIf {
predicate(any)
}
}
}
现在,您可以使用此 indexesOfAll
函数获取特定条件下所有项目的 indexes
。
things.indexesOfAll { it == "Jack" }.forEach {
things.set(it, 11)
}
您也可以对所有其他值执行相同的操作。
尽管其他答案解决了手头的问题,但仍有一个基本问题在起作用。通常您会希望避免使用 multi-typed 数组(或任何类型的集合)。
更好的解决方案是引入和抽象以将两种类型的数据表示为相同的 class 并使 class 实现 Comparable
接口。
一个实现示例:
sealed class Card(val name: String) : Comparable<Card> {
abstract val order: Int
override fun compareTo(other: Card): Int =
order - other.order
override fun toString(): String = name
class Number(value: Int) : Card(value.toString()) {
override val order: Int = value
}
object Ace : Card("Ace") {
override val order: Int = 1
}
object Jack : Card("Jack") {
override val order: Int = 11
}
object Queen : Card("Queen") {
override val order: Int = 12
}
object King : Card("King") {
override val order: Int = 13
}
}
那么你可以这样使用它:
println(listOf(Card.Number(2), Card.Ace, Card.Queen, Card.Number(3)).sorted())
我有给定的数组
val things = arrayOf<Any>("Jack", 8, 2, 6, "King", 5, 3, "Queen", "Jack");
下面是我用过的代码
things.set(things.indexOf("Jack"), 11);
things.set(things.indexOf("Queen"), 12);
things.set(things.indexOf("King"), 13);
things.sort();
things.set(things.indexOf(11), "Jack"));
things.set(things.indexOf(12), "Queen");
things.set(things.indexOf(13), "King");
things.joinToString(":");
things.forEach { System.out.print(it) }
这是我不断收到的错误
Unexpected tokens (use ';' to separate expressions on the same line)
Expecting an element
删除尾随括号后,出现以下错误
Exception in thread "main" java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')
at java.lang.String.compareTo (:-1)
at java.util.ComparableTimSort.binarySort (:-1)
at java.util.ComparableTimSort.sort (:-1)
问题是你有两次“杰克”。 things.set(things.indexOf("Jack"), 11);
只把第一个改成11,第二个不改
val things = arrayOf<Any>("Jack", 8, 2, 6, "King", 5, 3, "Queen", "Jack");
things.set(things.indexOf("Jack"), 11);
things.set(things.indexOf("Queen"), 12);
things.set(things.indexOf("King"), 13);
println(things.contentToString()) //prints [11, 8, 2, 6, 13, 5, 3, 12, Jack]
现在,我可能会怎么做,是这样的:
fun main() {
val things = arrayOf("Jack", 8, 2, 6, "King", 5, 3, "Queen", "Jack")
things.sortWith(compareBy { it.toInt() })
println(things.contentToString()) //prints [2, 3, 5, 6, 8, Jack, Jack, Queen, King]
}
val mapping = mapOf("Jack" to 11, "Queen" to 12, "King" to 13)
fun Any.toInt() : Int {
if (this is Int) return this
return mapping[this] ?: 0
}
您的列表中有 2 个 Jack
,因此当您使用 indexOf()
时,它 returns 是该项目第一次出现的索引。
things.set(things.indexOf("Jack"), 11);
things.set(things.indexOf("Queen"), 12);
things.set(things.indexOf("King"), 13);
这会将您的列表更改为
[11, 8, 2, 6, 13, 5, 3, 12, Jack]
现在,当您对 things
应用 sort()
操作时。它在 Jack
上抛出 ClassCastException
,因为它是 string
,而不是 int
。
要找到一个值的所有 indexes
,以便您可以替换它们,您可以创建一个 extension
函数,该函数 returns 一个值的所有索引的列表。
fun <T> Array<T>.indexesOfAll(predicate: (T) -> Boolean): List<Int> {
return mapIndexedNotNull { index, any ->
index.takeIf {
predicate(any)
}
}
}
现在,您可以使用此 indexesOfAll
函数获取特定条件下所有项目的 indexes
。
things.indexesOfAll { it == "Jack" }.forEach {
things.set(it, 11)
}
您也可以对所有其他值执行相同的操作。
尽管其他答案解决了手头的问题,但仍有一个基本问题在起作用。通常您会希望避免使用 multi-typed 数组(或任何类型的集合)。
更好的解决方案是引入和抽象以将两种类型的数据表示为相同的 class 并使 class 实现 Comparable
接口。
一个实现示例:
sealed class Card(val name: String) : Comparable<Card> {
abstract val order: Int
override fun compareTo(other: Card): Int =
order - other.order
override fun toString(): String = name
class Number(value: Int) : Card(value.toString()) {
override val order: Int = value
}
object Ace : Card("Ace") {
override val order: Int = 1
}
object Jack : Card("Jack") {
override val order: Int = 11
}
object Queen : Card("Queen") {
override val order: Int = 12
}
object King : Card("King") {
override val order: Int = 13
}
}
那么你可以这样使用它:
println(listOf(Card.Number(2), Card.Ace, Card.Queen, Card.Number(3)).sorted())