在 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())